Index: dnspython-1.12.0/dns/_compat.py
===================================================================
--- /dev/null
+++ dnspython-1.12.0/dns/_compat.py
@@ -0,0 +1,26 @@
+import sys
+
+
+if sys.version_info > (3,):
+    long = int
+    xrange = range
+else:
+    long = long
+    xrange = xrange
+
+# unicode / binary types
+if sys.version_info > (3,):
+    text_type = str
+    binary_type = bytes
+    string_types = (str,)
+    def xcmp(a, b):
+        if isinstance(a, str):
+            a = a.encode()
+        if isinstance(b, str):
+            b = b.encode()
+        return (a > b) - (a < b)
+else:
+    text_type = unicode
+    binary_type = str
+    string_types = (basestring,)
+    xcmp = cmp
Index: dnspython-1.12.0/dns/dnssec.py
===================================================================
--- dnspython-1.12.0.orig/dns/dnssec.py
+++ dnspython-1.12.0/dns/dnssec.py
@@ -15,7 +15,7 @@
 
 """Common DNSSEC-related functions and constants."""
 
-import cStringIO
+from io import BytesIO
 import struct
 import time
 
@@ -27,6 +27,7 @@ import dns.rdataset
 import dns.rdata
 import dns.rdatatype
 import dns.rdataclass
+from ._compat import string_types
 
 class UnsupportedAlgorithm(dns.exception.DNSException):
     """Raised if an algorithm is not supported."""
@@ -52,27 +53,28 @@ PRIVATEDNS = 253
 PRIVATEOID = 254
 
 _algorithm_by_text = {
-    'RSAMD5' : RSAMD5,
-    'DH' : DH,
-    'DSA' : DSA,
-    'ECC' : ECC,
-    'RSASHA1' : RSASHA1,
-    'DSANSEC3SHA1' : DSANSEC3SHA1,
-    'RSASHA1NSEC3SHA1' : RSASHA1NSEC3SHA1,
-    'RSASHA256' : RSASHA256,
-    'RSASHA512' : RSASHA512,
-    'INDIRECT' : INDIRECT,
-    'ECDSAP256SHA256' : ECDSAP256SHA256,
-    'ECDSAP384SHA384' : ECDSAP384SHA384,
-    'PRIVATEDNS' : PRIVATEDNS,
-    'PRIVATEOID' : PRIVATEOID,
-    }
+    'RSAMD5': RSAMD5,
+    'DH': DH,
+    'DSA': DSA,
+    'ECC': ECC,
+    'RSASHA1': RSASHA1,
+    'DSANSEC3SHA1': DSANSEC3SHA1,
+    'RSASHA1NSEC3SHA1': RSASHA1NSEC3SHA1,
+    'RSASHA256': RSASHA256,
+    'RSASHA512': RSASHA512,
+    'INDIRECT': INDIRECT,
+    'ECDSAP256SHA256': ECDSAP256SHA256,
+    'ECDSAP384SHA384': ECDSAP384SHA384,
+    'PRIVATEDNS': PRIVATEDNS,
+    'PRIVATEOID': PRIVATEOID,
+}
 
 # We construct the inverse mapping programmatically to ensure that we
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be true inverse.
 
-_algorithm_by_value = dict([(y, x) for x, y in _algorithm_by_text.iteritems()])
+_algorithm_by_value = dict((y, x) for x, y in _algorithm_by_text.items())
+
 
 def algorithm_from_text(text):
     """Convert text into a DNSSEC algorithm value
@@ -83,6 +85,7 @@ def algorithm_from_text(text):
         value = int(text)
     return value
 
+
 def algorithm_to_text(value):
     """Convert a DNSSEC algorithm value to text
     @rtype: string"""
@@ -92,35 +95,40 @@ def algorithm_to_text(value):
         text = str(value)
     return text
 
+
 def _to_rdata(record, origin):
-    s = cStringIO.StringIO()
+    s = BytesIO()
     record.to_wire(s, origin=origin)
     return s.getvalue()
 
+
 def key_id(key, origin=None):
     rdata = _to_rdata(key, origin)
+    rdata = bytearray(rdata)
     if key.algorithm == RSAMD5:
-        return (ord(rdata[-3]) << 8) + ord(rdata[-2])
+        return (rdata[-3] << 8) + rdata[-2]
     else:
         total = 0
         for i in range(len(rdata) // 2):
-            total += (ord(rdata[2 * i]) << 8) + ord(rdata[2 * i + 1])
+            total += (rdata[2 * i] << 8) + \
+                rdata[2 * i + 1]
         if len(rdata) % 2 != 0:
-            total += ord(rdata[len(rdata) - 1]) << 8
-        total += ((total >> 16) & 0xffff);
+            total += rdata[len(rdata) - 1] << 8
+        total += ((total >> 16) & 0xffff)
         return total & 0xffff
 
+
 def make_ds(name, key, algorithm, origin=None):
     if algorithm.upper() == 'SHA1':
         dsalg = 1
-        hash = dns.hash.get('SHA1')()
+        hash = dns.hash.hashes['SHA1']()
     elif algorithm.upper() == 'SHA256':
         dsalg = 2
-        hash = dns.hash.get('SHA256')()
+        hash = dns.hash.hashes['SHA256']()
     else:
-        raise UnsupportedAlgorithm, 'unsupported algorithm "%s"' % algorithm
+        raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
 
-    if isinstance(name, (str, unicode)):
+    if isinstance(name, string_types):
         name = dns.name.from_text(name, origin)
     hash.update(name.canonicalize().to_wire())
     hash.update(_to_rdata(key, origin))
@@ -130,8 +138,9 @@ def make_ds(name, key, algorithm, origin
     return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0,
                                len(dsrdata))
 
+
 def _find_candidate_keys(keys, rrsig):
-    candidate_keys=[]
+    candidate_keys = []
     value = keys.get(rrsig.signer)
     if value is None:
         return None
@@ -145,49 +154,59 @@ def _find_candidate_keys(keys, rrsig):
         rdataset = value
     for rdata in rdataset:
         if rdata.algorithm == rrsig.algorithm and \
-               key_id(rdata) == rrsig.key_tag:
+                key_id(rdata) == rrsig.key_tag:
             candidate_keys.append(rdata)
     return candidate_keys
 
+
 def _is_rsa(algorithm):
     return algorithm in (RSAMD5, RSASHA1,
                          RSASHA1NSEC3SHA1, RSASHA256,
                          RSASHA512)
 
+
 def _is_dsa(algorithm):
     return algorithm in (DSA, DSANSEC3SHA1)
 
+
 def _is_ecdsa(algorithm):
     return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384))
 
+
 def _is_md5(algorithm):
     return algorithm == RSAMD5
 
+
 def _is_sha1(algorithm):
     return algorithm in (DSA, RSASHA1,
                          DSANSEC3SHA1, RSASHA1NSEC3SHA1)
 
+
 def _is_sha256(algorithm):
     return algorithm in (RSASHA256, ECDSAP256SHA256)
 
+
 def _is_sha384(algorithm):
     return algorithm == ECDSAP384SHA384
 
+
 def _is_sha512(algorithm):
     return algorithm == RSASHA512
 
+
 def _make_hash(algorithm):
     if _is_md5(algorithm):
-        return dns.hash.get('MD5')()
+        return dns.hash.hashes['MD5']()
     if _is_sha1(algorithm):
-        return dns.hash.get('SHA1')()
+        return dns.hash.hashes['SHA1']()
     if _is_sha256(algorithm):
-        return dns.hash.get('SHA256')()
+        return dns.hash.hashes['SHA256']()
     if _is_sha384(algorithm):
-        return dns.hash.get('SHA384')()
+        return dns.hash.hashes['SHA384']()
     if _is_sha512(algorithm):
-        return dns.hash.get('SHA512')()
-    raise ValidationFailure, 'unknown hash for algorithm %u' % algorithm
+        return dns.hash.hashes['SHA512']()
+    raise ValidationFailure('unknown hash for algorithm %u' % algorithm)
+
 
 def _make_algorithm_id(algorithm):
     if _is_md5(algorithm):
@@ -199,13 +218,14 @@ def _make_algorithm_id(algorithm):
     elif _is_sha512(algorithm):
         oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
     else:
-        raise ValidationFailure, 'unknown algorithm %u' % algorithm
+        raise ValidationFailure('unknown algorithm %u' % algorithm)
     olen = len(oid)
     dlen = _make_hash(algorithm).digest_size
     idbytes = [0x30] + [8 + olen + dlen] + \
               [0x30, olen + 4] + [0x06, olen] + oid + \
               [0x05, 0x00] + [0x04, dlen]
-    return ''.join(map(chr, idbytes))
+    return struct.pack('!%dB' % len(idbytes), *idbytes)
+
 
 def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
     """Validate an RRset against a single signature rdata
@@ -219,7 +239,8 @@ def _validate_rrsig(rrset, rrsig, keys,
     @param rrsig: The signature rdata
     @type rrsig: dns.rrset.Rdata
     @param keys: The key dictionary.
-    @type keys: a dictionary keyed by dns.name.Name with node or rdataset values
+    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
+    values
     @param origin: The origin to use for relative names
     @type origin: dns.name.Name or None
     @param now: The time to use when validating the signatures.  The default
@@ -227,15 +248,15 @@ def _validate_rrsig(rrset, rrsig, keys,
     @type now: int
     """
 
-    if isinstance(origin, (str, unicode)):
+    if isinstance(origin, string_types):
         origin = dns.name.from_text(origin, dns.name.root)
 
     for candidate_key in _find_candidate_keys(keys, rrsig):
         if not candidate_key:
-            raise ValidationFailure, 'unknown key'
+            raise ValidationFailure('unknown key')
 
-        # For convenience, allow the rrset to be specified as a (name, rdataset)
-        # tuple as well as a proper rrset
+        # For convenience, allow the rrset to be specified as a (name,
+        # rdataset) tuple as well as a proper rrset
         if isinstance(rrset, tuple):
             rrname = rrset[0]
             rdataset = rrset[1]
@@ -246,21 +267,21 @@ def _validate_rrsig(rrset, rrsig, keys,
         if now is None:
             now = time.time()
         if rrsig.expiration < now:
-            raise ValidationFailure, 'expired'
+            raise ValidationFailure('expired')
         if rrsig.inception > now:
-            raise ValidationFailure, 'not yet valid'
+            raise ValidationFailure('not yet valid')
 
         hash = _make_hash(rrsig.algorithm)
 
         if _is_rsa(rrsig.algorithm):
             keyptr = candidate_key.key
-            (bytes,) = struct.unpack('!B', keyptr[0:1])
+            (bytes_,) = struct.unpack('!B', keyptr[0:1])
             keyptr = keyptr[1:]
-            if bytes == 0:
-                (bytes,) = struct.unpack('!H', keyptr[0:2])
+            if bytes_ == 0:
+                (bytes_,) = struct.unpack('!H', keyptr[0:2])
                 keyptr = keyptr[2:]
-            rsa_e = keyptr[0:bytes]
-            rsa_n = keyptr[bytes:]
+            rsa_e = keyptr[0:bytes_]
+            rsa_n = keyptr[bytes_:]
             keylen = len(rsa_n) * 8
             pubkey = Crypto.PublicKey.RSA.construct(
                 (Crypto.Util.number.bytes_to_long(rsa_n),
@@ -290,14 +311,12 @@ def _validate_rrsig(rrset, rrsig, keys,
             if rrsig.algorithm == ECDSAP256SHA256:
                 curve = ecdsa.curves.NIST256p
                 key_len = 32
-                digest_len = 32
             elif rrsig.algorithm == ECDSAP384SHA384:
                 curve = ecdsa.curves.NIST384p
                 key_len = 48
-                digest_len = 48
             else:
                 # shouldn't happen
-                raise ValidationFailure, 'unknown ECDSA curve'
+                raise ValidationFailure('unknown ECDSA curve')
             keyptr = candidate_key.key
             x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len])
             y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2])
@@ -311,7 +330,7 @@ def _validate_rrsig(rrset, rrsig, keys,
             sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r),
                                         Crypto.Util.number.bytes_to_long(s))
         else:
-            raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
+            raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
 
         hash.update(_to_rdata(rrsig, origin)[:18])
         hash.update(rrsig.signer.to_digestable(origin))
@@ -322,7 +341,7 @@ def _validate_rrsig(rrset, rrsig, keys,
         rrnamebuf = rrname.to_digestable(origin)
         rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass,
                               rrsig.original_ttl)
-        rrlist = sorted(rdataset);
+        rrlist = sorted(rdataset)
         for rr in rrlist:
             hash.update(rrnamebuf)
             hash.update(rrfixed)
@@ -337,18 +356,20 @@ def _validate_rrsig(rrset, rrsig, keys,
             # PKCS1 algorithm identifier goop
             digest = _make_algorithm_id(rrsig.algorithm) + digest
             padlen = keylen // 8 - len(digest) - 3
-            digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest
+            digest = struct.pack('!%dB' % (2 + padlen + 1),
+                                 *([0, 1] + [0xFF] * padlen + [0])) + digest
         elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm):
             pass
         else:
             # Raise here for code clarity; this won't actually ever happen
             # since if the algorithm is really unknown we'd already have
             # raised an exception above
-            raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
+            raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
 
         if pubkey.verify(digest, sig):
             return
-    raise ValidationFailure, 'verify failure'
+    raise ValidationFailure('verify failure')
+
 
 def _validate(rrset, rrsigset, keys, origin=None, now=None):
     """Validate an RRset
@@ -360,7 +381,8 @@ def _validate(rrset, rrsigset, keys, ori
     @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
     tuple
     @param keys: The key dictionary.
-    @type keys: a dictionary keyed by dns.name.Name with node or rdataset values
+    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
+    values
     @param origin: The origin to use for relative names
     @type origin: dns.name.Name or None
     @param now: The time to use when validating the signatures.  The default
@@ -368,7 +390,7 @@ def _validate(rrset, rrsigset, keys, ori
     @type now: int
     """
 
-    if isinstance(origin, (str, unicode)):
+    if isinstance(origin, string_types):
         origin = dns.name.from_text(origin, dns.name.root)
 
     if isinstance(rrset, tuple):
@@ -386,18 +408,19 @@ def _validate(rrset, rrsigset, keys, ori
     rrname = rrname.choose_relativity(origin)
     rrsigname = rrname.choose_relativity(origin)
     if rrname != rrsigname:
-        raise ValidationFailure, "owner names do not match"
+        raise ValidationFailure("owner names do not match")
 
     for rrsig in rrsigrdataset:
         try:
             _validate_rrsig(rrset, rrsig, keys, origin, now)
             return
-        except ValidationFailure, e:
+        except ValidationFailure:
             pass
-    raise ValidationFailure, "no RRSIGs validated"
+    raise ValidationFailure("no RRSIGs validated")
+
 
 def _need_pycrypto(*args, **kwargs):
-    raise NotImplementedError, "DNSSEC validation requires pycrypto"
+    raise NotImplementedError("DNSSEC validation requires pycrypto")
 
 try:
     import Crypto.PublicKey.RSA
@@ -419,9 +442,11 @@ try:
     _have_ecdsa = True
 
     class ECKeyWrapper(object):
+
         def __init__(self, key, key_len):
             self.key = key
             self.key_len = key_len
+
         def verify(self, digest, sig):
             diglong = Crypto.Util.number.bytes_to_long(digest)
             return self.key.pubkey.verifies(diglong, sig)
Index: dnspython-1.12.0/dns/e164.py
===================================================================
--- dnspython-1.12.0.orig/dns/e164.py
+++ dnspython-1.12.0/dns/e164.py
@@ -19,12 +19,15 @@
 @type public_enum_domain: dns.name.Name object
 """
 
+
 import dns.exception
 import dns.name
 import dns.resolver
+from ._compat import string_types
 
 public_enum_domain = dns.name.from_text('e164.arpa.')
 
+
 def from_e164(text, origin=public_enum_domain):
     """Convert an E.164 number in textual form into a Name object whose
     value is the ENUM domain name for that number.
@@ -39,6 +42,7 @@ def from_e164(text, origin=public_enum_d
     parts.reverse()
     return dns.name.from_text('.'.join(parts), origin=origin)
 
+
 def to_e164(name, origin=public_enum_domain, want_plus_prefix=True):
     """Convert an ENUM domain name into an E.164 number.
     @param name: the ENUM domain name.
@@ -50,17 +54,18 @@ def to_e164(name, origin=public_enum_dom
     returned number.
     @rtype: str
     """
-    if not origin is None:
+    if origin is not None:
         name = name.relativize(origin)
     dlabels = [d for d in name.labels if (d.isdigit() and len(d) == 1)]
     if len(dlabels) != len(name.labels):
         raise dns.exception.SyntaxError('non-digit labels in ENUM domain name')
     dlabels.reverse()
-    text = ''.join(dlabels)
+    text = b''.join(dlabels)
     if want_plus_prefix:
-        text = '+' + text
+        text = b'+' + text
     return text
 
+
 def query(number, domains, resolver=None):
     """Look for NAPTR RRs for the specified number in the specified domains.
 
@@ -69,7 +74,7 @@ def query(number, domains, resolver=None
     if resolver is None:
         resolver = dns.resolver.get_default_resolver()
     for domain in domains:
-        if isinstance(domain, (str, unicode)):
+        if isinstance(domain, string_types):
             domain = dns.name.from_text(domain)
         qname = dns.e164.from_e164(number, domain)
         try:
Index: dnspython-1.12.0/dns/edns.py
===================================================================
--- dnspython-1.12.0.orig/dns/edns.py
+++ dnspython-1.12.0/dns/edns.py
@@ -14,10 +14,12 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 """EDNS Options"""
-
+from dns._compat import xcmp
 NSID = 3
 
+
 class Option(object):
+
     """Base class for all EDNS option types.
     """
 
@@ -33,6 +35,7 @@ class Option(object):
         """
         raise NotImplementedError
 
+    @classmethod
     def from_wire(cls, otype, wire, current, olen):
         """Build an EDNS option object from wire format
 
@@ -47,11 +50,10 @@ class Option(object):
         @rtype: dns.edns.Option instance"""
         raise NotImplementedError
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         """Compare an EDNS option with another option of the same type.
-        Return < 0 if self < other, 0 if self == other, and > 0 if self > other.
+        Return < 0 if self < other, 0 if self == other,
+        and > 0 if self > other.
         """
         raise NotImplementedError
 
@@ -71,30 +73,31 @@ class Option(object):
 
     def __lt__(self, other):
         if not isinstance(other, Option) or \
-               self.otype != other.otype:
+                self.otype != other.otype:
             return NotImplemented
         return self._cmp(other) < 0
 
     def __le__(self, other):
         if not isinstance(other, Option) or \
-               self.otype != other.otype:
+                self.otype != other.otype:
             return NotImplemented
         return self._cmp(other) <= 0
 
     def __ge__(self, other):
         if not isinstance(other, Option) or \
-               self.otype != other.otype:
+                self.otype != other.otype:
             return NotImplemented
         return self._cmp(other) >= 0
 
     def __gt__(self, other):
         if not isinstance(other, Option) or \
-               self.otype != other.otype:
+                self.otype != other.otype:
             return NotImplemented
         return self._cmp(other) > 0
 
 
 class GenericOption(Option):
+
     """Generate Rdata Class
 
     This class is used for EDNS option types for which we have no better
@@ -108,13 +111,12 @@ class GenericOption(Option):
     def to_wire(self, file):
         file.write(self.data)
 
+    @classmethod
     def from_wire(cls, otype, wire, current, olen):
         return cls(otype, wire[current : current + olen])
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-	return cmp(self.data, other.data)
+        return xcmp(self.data, other.data)
 
 _type_to_class = {
 }
Index: dnspython-1.12.0/dns/entropy.py
===================================================================
--- dnspython-1.12.0.orig/dns/entropy.py
+++ dnspython-1.12.0/dns/entropy.py
@@ -15,12 +15,15 @@
 
 import os
 import time
+from ._compat import long, binary_type
 try:
     import threading as _threading
 except ImportError:
     import dummy_threading as _threading
 
+
 class EntropyPool(object):
+
     def __init__(self, seed=None):
         self.pool_index = 0
         self.digest = None
@@ -39,9 +42,9 @@ class EntropyPool(object):
                 import md5
                 self.hash = md5.new()
                 self.hash_len = 16
-        self.pool = '\0' * self.hash_len
-        if not seed is None:
-            self.stir(seed)
+        self.pool = bytearray(b'\0' * self.hash_len)
+        if seed is not None:
+            self.stir(bytearray(seed))
             self.seeded = True
         else:
             self.seeded = False
@@ -50,14 +53,12 @@ class EntropyPool(object):
         if not already_locked:
             self.lock.acquire()
         try:
-            bytes = [ord(c) for c in self.pool]
             for c in entropy:
                 if self.pool_index == self.hash_len:
                     self.pool_index = 0
-                b = ord(c) & 0xff
-                bytes[self.pool_index] ^= b
+                b = c & 0xff
+                self.pool[self.pool_index] ^= b
                 self.pool_index += 1
-            self.pool = ''.join([chr(c) for c in bytes])
         finally:
             if not already_locked:
                 self.lock.release()
@@ -68,7 +69,7 @@ class EntropyPool(object):
                 seed = os.urandom(16)
             except:
                 try:
-                    r = file('/dev/urandom', 'r', 0)
+                    r = open('/dev/urandom', 'rb', 0)
                     try:
                         seed = r.read(16)
                     finally:
@@ -76,18 +77,19 @@ class EntropyPool(object):
                 except:
                     seed = str(time.time())
             self.seeded = True
+            seed = bytearray(seed)
             self.stir(seed, True)
 
     def random_8(self):
         self.lock.acquire()
-        self._maybe_seed()
         try:
+            self._maybe_seed()
             if self.digest is None or self.next_byte == self.hash_len:
-                self.hash.update(self.pool)
-                self.digest = self.hash.digest()
+                self.hash.update(binary_type(self.pool))
+                self.digest = bytearray(self.hash.digest())
                 self.stir(self.digest, True)
                 self.next_byte = 0
-            value = ord(self.digest[self.next_byte])
+            value = self.digest[self.next_byte]
             self.next_byte += 1
         finally:
             self.lock.release()
@@ -101,23 +103,25 @@ class EntropyPool(object):
 
     def random_between(self, first, last):
         size = last - first + 1
-        if size > 4294967296L:
+        if size > long(4294967296):
             raise ValueError('too big')
         if size > 65536:
             rand = self.random_32
-            max = 4294967295L
+            max = long(4294967295)
         elif size > 256:
             rand = self.random_16
             max = 65535
         else:
             rand = self.random_8
             max = 255
-	return (first + size * rand() // (max + 1))
+        return (first + size * rand() // (max + 1))
 
 pool = EntropyPool()
 
+
 def random_16():
     return pool.random_16()
 
+
 def between(first, last):
     return pool.random_between(first, last)
Index: dnspython-1.12.0/dns/flags.py
===================================================================
--- dnspython-1.12.0.orig/dns/flags.py
+++ dnspython-1.12.0/dns/flags.py
@@ -30,17 +30,17 @@ CD = 0x0010
 DO = 0x8000
 
 _by_text = {
-    'QR' : QR,
-    'AA' : AA,
-    'TC' : TC,
-    'RD' : RD,
-    'RA' : RA,
-    'AD' : AD,
-    'CD' : CD
+    'QR': QR,
+    'AA': AA,
+    'TC': TC,
+    'RD': RD,
+    'RA': RA,
+    'AD': AD,
+    'CD': CD
 }
 
 _edns_by_text = {
-    'DO' : DO
+    'DO': DO
 }
 
 
@@ -48,12 +48,13 @@ _edns_by_text = {
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mappings not to be true inverses.
 
-_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
+_by_value = dict((y, x) for x, y in _by_text.items())
+
+_edns_by_value = dict((y, x) for x, y in _edns_by_text.items())
 
-_edns_by_value = dict([(y, x) for x, y in _edns_by_text.iteritems()])
 
 def _order_flags(table):
-    order = list(table.iteritems())
+    order = list(table.items())
     order.sort()
     order.reverse()
     return order
@@ -62,6 +63,7 @@ _flags_order = _order_flags(_by_value)
 
 _edns_flags_order = _order_flags(_edns_by_value)
 
+
 def _from_text(text, table):
     flags = 0
     tokens = text.split()
@@ -69,6 +71,7 @@ def _from_text(text, table):
         flags = flags | table[t.upper()]
     return flags
 
+
 def _to_text(flags, table, order):
     text_flags = []
     for k, v in order:
@@ -76,6 +79,7 @@ def _to_text(flags, table, order):
             text_flags.append(v)
     return ' '.join(text_flags)
 
+
 def from_text(text):
     """Convert a space-separated list of flag text values into a flags
     value.
@@ -83,13 +87,14 @@ def from_text(text):
 
     return _from_text(text, _by_text)
 
+
 def to_text(flags):
     """Convert a flags value into a space-separated list of flag text
     values.
     @rtype: string"""
 
     return _to_text(flags, _by_value, _flags_order)
-    
+
 
 def edns_from_text(text):
     """Convert a space-separated list of EDNS flag text values into a EDNS
@@ -98,6 +103,7 @@ def edns_from_text(text):
 
     return _from_text(text, _edns_by_text)
 
+
 def edns_to_text(flags):
     """Convert an EDNS flags value into a space-separated list of EDNS flag
     text values.
Index: dnspython-1.12.0/dns/grange.py
===================================================================
--- dnspython-1.12.0.orig/dns/grange.py
+++ dnspython-1.12.0/dns/grange.py
@@ -17,6 +17,7 @@
 
 import dns
 
+
 def from_text(text):
     """Convert the text form of a range in a GENERATE statement to an
     integer.
@@ -28,7 +29,6 @@ def from_text(text):
     """
     # TODO, figure out the bounds on start, stop and step.
 
-    import pdb
     step = 1
     cur = ''
     state = 0
Index: dnspython-1.12.0/dns/hash.py
===================================================================
--- dnspython-1.12.0.orig/dns/hash.py
+++ dnspython-1.12.0/dns/hash.py
@@ -16,52 +16,17 @@
 """Hashing backwards compatibility wrapper"""
 
 import sys
+import hashlib
 
-_hashes = None
 
-def _need_later_python(alg):
-    def func(*args, **kwargs):
-        raise NotImplementedError("TSIG algorithm " + alg +
-                                  " requires Python 2.5.2 or later")
-    return func
+hashes = {}
+hashes['MD5'] = hashlib.md5
+hashes['SHA1'] = hashlib.sha1
+hashes['SHA224'] = hashlib.sha224
+hashes['SHA256'] = hashlib.sha256
+hashes['SHA384'] = hashlib.sha384
+hashes['SHA512'] = hashlib.sha512
 
-def _setup():
-    global _hashes
-    _hashes = {}
-    try:
-        import hashlib
-        _hashes['MD5'] = hashlib.md5
-        _hashes['SHA1'] = hashlib.sha1
-        _hashes['SHA224'] = hashlib.sha224
-        _hashes['SHA256'] = hashlib.sha256
-        if sys.hexversion >= 0x02050200:
-            _hashes['SHA384'] = hashlib.sha384
-            _hashes['SHA512'] = hashlib.sha512
-        else:
-            _hashes['SHA384'] = _need_later_python('SHA384')
-            _hashes['SHA512'] = _need_later_python('SHA512')
-
-        if sys.hexversion < 0x02050000:
-            # hashlib doesn't conform to PEP 247: API for
-            # Cryptographic Hash Functions, which hmac before python
-            # 2.5 requires, so add the necessary items.
-            class HashlibWrapper:
-                def __init__(self, basehash):
-                    self.basehash = basehash
-                    self.digest_size = self.basehash().digest_size
-
-                def new(self, *args, **kwargs):
-                    return self.basehash(*args, **kwargs)
-
-            for name in _hashes:
-                _hashes[name] = HashlibWrapper(_hashes[name])
-
-    except ImportError:
-        import md5, sha
-        _hashes['MD5'] =  md5
-        _hashes['SHA1'] = sha
 
 def get(algorithm):
-    if _hashes is None:
-        _setup()
-    return _hashes[algorithm.upper()]
+    return hashes[algorithm.upper()]
Index: dnspython-1.12.0/dns/inet.py
===================================================================
--- dnspython-1.12.0.orig/dns/inet.py
+++ dnspython-1.12.0/dns/inet.py
@@ -34,6 +34,7 @@ try:
 except AttributeError:
     AF_INET6 = 9999
 
+
 def inet_pton(family, text):
     """Convert the textual form of a network address into its binary form.
 
@@ -45,7 +46,7 @@ def inet_pton(family, text):
     implemented.
     @rtype: string
     """
-    
+
     if family == AF_INET:
         return dns.ipv4.inet_aton(text)
     elif family == AF_INET6:
@@ -53,6 +54,7 @@ def inet_pton(family, text):
     else:
         raise NotImplementedError
 
+
 def inet_ntop(family, address):
     """Convert the binary form of a network address into its textual form.
 
@@ -71,6 +73,7 @@ def inet_ntop(family, address):
     else:
         raise NotImplementedError
 
+
 def af_for_address(text):
     """Determine the address family of a textual-form network address.
 
@@ -80,15 +83,16 @@ def af_for_address(text):
     @rtype: int
     """
     try:
-        junk = dns.ipv4.inet_aton(text)
+        dns.ipv4.inet_aton(text)
         return AF_INET
     except:
         try:
-            junk = dns.ipv6.inet_aton(text)
+            dns.ipv6.inet_aton(text)
             return AF_INET6
         except:
             raise ValueError
 
+
 def is_multicast(text):
     """Is the textual-form network address a multicast address?
 
@@ -105,4 +109,3 @@ def is_multicast(text):
             return (first == 255)
         except:
             raise ValueError
-    
Index: dnspython-1.12.0/dns/ipv4.py
===================================================================
--- dnspython-1.12.0.orig/dns/ipv4.py
+++ dnspython-1.12.0/dns/ipv4.py
@@ -18,6 +18,7 @@
 import struct
 
 import dns.exception
+from ._compat import binary_type
 
 def inet_ntoa(address):
     """Convert an IPv4 address in network form to text form.
@@ -28,8 +29,10 @@ def inet_ntoa(address):
     """
     if len(address) != 4:
         raise dns.exception.SyntaxError
-    return '%u.%u.%u.%u' % (ord(address[0]), ord(address[1]),
-                            ord(address[2]), ord(address[3]))
+    if not isinstance(address, bytearray):
+        address = bytearray(address)
+    return (u'%u.%u.%u.%u' % (address[0], address[1],
+                              address[2], address[3])).encode()
 
 def inet_aton(text):
     """Convert an IPv4 address in text form to network form.
@@ -38,7 +41,9 @@ def inet_aton(text):
     @type text: string
     @returns: string
     """
-    parts = text.split('.')
+    if not isinstance(text, binary_type):
+        text = text.encode()
+    parts = text.split(b'.')
     if len(parts) != 4:
         raise dns.exception.SyntaxError
     for part in parts:
Index: dnspython-1.12.0/dns/ipv6.py
===================================================================
--- dnspython-1.12.0.orig/dns/ipv6.py
+++ dnspython-1.12.0/dns/ipv6.py
@@ -16,11 +16,13 @@
 """IPv6 helper functions."""
 
 import re
+import binascii
 
 import dns.exception
 import dns.ipv4
+from ._compat import xrange, binary_type
 
-_leading_zero = re.compile(r'0+([0-9a-f]+)')
+_leading_zero = re.compile(b'0+([0-9a-f]+)')
 
 def inet_ntoa(address):
     """Convert a network format IPv6 address into text.
@@ -33,7 +35,7 @@ def inet_ntoa(address):
 
     if len(address) != 16:
         raise ValueError("IPv6 addresses are 16 bytes long")
-    hex = address.encode('hex_codec')
+    hex = binascii.hexlify(address)
     chunks = []
     i = 0
     l = len(hex)
@@ -55,7 +57,7 @@ def inet_ntoa(address):
     start = -1
     last_was_zero = False
     for i in xrange(8):
-        if chunks[i] != '0':
+        if chunks[i] != b'0':
             if last_was_zero:
                 end = i
                 current_len = end - start
@@ -75,23 +77,23 @@ def inet_ntoa(address):
     if best_len > 1:
         if best_start == 0 and \
            (best_len == 6 or
-            best_len == 5 and chunks[5] == 'ffff'):
+            best_len == 5 and chunks[5] == b'ffff'):
             # We have an embedded IPv4 address
             if best_len == 6:
-                prefix = '::'
+                prefix = b'::'
             else:
-                prefix = '::ffff:'
+                prefix = b'::ffff:'
             hex = prefix + dns.ipv4.inet_ntoa(address[12:])
         else:
-            hex = ':'.join(chunks[:best_start]) + '::' + \
-                  ':'.join(chunks[best_start + best_len:])
+            hex = b':'.join(chunks[:best_start]) + b'::' + \
+                  b':'.join(chunks[best_start + best_len:])
     else:
-        hex = ':'.join(chunks)
+        hex = b':'.join(chunks)
     return hex
 
-_v4_ending = re.compile(r'(.*):(\d+\.\d+\.\d+\.\d+)$')
-_colon_colon_start = re.compile(r'::.*')
-_colon_colon_end = re.compile(r'.*::$')
+_v4_ending = re.compile(b'(.*):(\d+\.\d+\.\d+\.\d+)$')
+_colon_colon_start = re.compile(b'::.*')
+_colon_colon_end = re.compile(b'.*::$')
 
 def inet_aton(text):
     """Convert a text format IPv6 address into network format.
@@ -105,17 +107,19 @@ def inet_aton(text):
     #
     # Our aim here is not something fast; we just want something that works.
     #
+    if not isinstance(text, binary_type):
+        text = text.encode()
 
-    if text == '::':
-        text = '0::'
+    if text == b'::':
+        text = b'0::'
     #
     # Get rid of the icky dot-quad syntax if we have it.
     #
     m = _v4_ending.match(text)
     if not m is None:
-        b = dns.ipv4.inet_aton(m.group(2))
-        text = "%s:%02x%02x:%02x%02x" % (m.group(1), ord(b[0]), ord(b[1]),
-                                         ord(b[2]), ord(b[3]))
+        b = bytearray(dns.ipv4.inet_aton(m.group(2)))
+        text = (u"%s:%02x%02x:%02x%02x" % (m.group(1).decode(), b[0], b[1],
+                                           b[2], b[3])).encode()
     #
     # Try to turn '::<whatever>' into ':<whatever>'; if no match try to
     # turn '<whatever>::' into '<whatever>:'
@@ -130,39 +134,39 @@ def inet_aton(text):
     #
     # Now canonicalize into 8 chunks of 4 hex digits each
     #
-    chunks = text.split(':')
+    chunks = text.split(b':')
     l = len(chunks)
     if l > 8:
         raise dns.exception.SyntaxError
     seen_empty = False
     canonical = []
     for c in chunks:
-        if c == '':
+        if c == b'':
             if seen_empty:
                 raise dns.exception.SyntaxError
             seen_empty = True
             for i in xrange(0, 8 - l + 1):
-                canonical.append('0000')
+                canonical.append(b'0000')
         else:
             lc = len(c)
             if lc > 4:
                 raise dns.exception.SyntaxError
             if lc != 4:
-                c = ('0' * (4 - lc)) + c
+                c = (b'0' * (4 - lc)) + c
             canonical.append(c)
     if l < 8 and not seen_empty:
         raise dns.exception.SyntaxError
-    text = ''.join(canonical)
+    text = b''.join(canonical)
 
     #
     # Finally we can go to binary.
     #
     try:
-        return text.decode('hex_codec')
-    except TypeError:
+        return binascii.unhexlify(text)
+    except (binascii.Error, TypeError):
         raise dns.exception.SyntaxError
 
-_mapped_prefix = '\x00' * 10 + '\xff\xff'
+_mapped_prefix = b'\x00' * 10 + b'\xff\xff'
 
 def is_mapped(address):
     return address.startswith(_mapped_prefix)
Index: dnspython-1.12.0/dns/message.py
===================================================================
--- dnspython-1.12.0.orig/dns/message.py
+++ dnspython-1.12.0/dns/message.py
@@ -15,8 +15,9 @@
 
 """DNS Messages"""
 
-import cStringIO
-import random
+from __future__ import absolute_import
+
+from io import StringIO
 import struct
 import sys
 import time
@@ -36,6 +37,8 @@ import dns.renderer
 import dns.tsig
 import dns.wiredata
 
+from ._compat import long, xrange, string_types
+
 class ShortHeader(dns.exception.FormError):
     """Raised if the DNS packet passed to from_wire() is too short."""
     pass
@@ -173,7 +176,7 @@ class Message(object):
         self.index = {}
 
     def __repr__(self):
-        return '<DNS message, ID ' + `self.id` + '>'
+        return '<DNS message, ID ' + repr(self.id) + '>'
 
     def __str__(self):
         return self.to_text()
@@ -187,41 +190,45 @@ class Message(object):
         @rtype: string
         """
 
-        s = cStringIO.StringIO()
-        print >> s, 'id %d' % self.id
-        print >> s, 'opcode %s' % \
-              dns.opcode.to_text(dns.opcode.from_flags(self.flags))
+        s = StringIO()
+        s.write(u'id %d\n' % self.id)
+        s.write(u'opcode %s\n' %
+                dns.opcode.to_text(dns.opcode.from_flags(self.flags)))
         rc = dns.rcode.from_flags(self.flags, self.ednsflags)
-        print >> s, 'rcode %s' % dns.rcode.to_text(rc)
-        print >> s, 'flags %s' % dns.flags.to_text(self.flags)
+        s.write(u'rcode %s\n' % dns.rcode.to_text(rc))
+        s.write(u'flags %s\n' % dns.flags.to_text(self.flags))
         if self.edns >= 0:
-            print >> s, 'edns %s' % self.edns
+            s.write(u'edns %s\n' % self.edns)
             if self.ednsflags != 0:
-                print >> s, 'eflags %s' % \
-                      dns.flags.edns_to_text(self.ednsflags)
-            print >> s, 'payload', self.payload
+                s.write(u'eflags %s\n' %
+                        dns.flags.edns_to_text(self.ednsflags))
+            s.write(u'payload %d\n' % self.payload)
         is_update = dns.opcode.is_update(self.flags)
         if is_update:
-            print >> s, ';ZONE'
+            s.write(u';ZONE\n')
         else:
-            print >> s, ';QUESTION'
+            s.write(u';QUESTION\n')
         for rrset in self.question:
-            print >> s, rrset.to_text(origin, relativize, **kw)
+            s.write(rrset.to_text(origin, relativize, **kw))
+            s.write(u'\n')
         if is_update:
-            print >> s, ';PREREQ'
+            s.write(u';PREREQ\n')
         else:
-            print >> s, ';ANSWER'
+            s.write(u';ANSWER\n')
         for rrset in self.answer:
-            print >> s, rrset.to_text(origin, relativize, **kw)
+            s.write(rrset.to_text(origin, relativize, **kw))
+            s.write(u'\n')
         if is_update:
-            print >> s, ';UPDATE'
+            s.write(u';UPDATE\n')
         else:
-            print >> s, ';AUTHORITY'
+            s.write(u';AUTHORITY\n')
         for rrset in self.authority:
-            print >> s, rrset.to_text(origin, relativize, **kw)
-        print >> s, ';ADDITIONAL'
+            s.write(rrset.to_text(origin, relativize, **kw))
+            s.write(u'\n')
+        s.write(u';ADDITIONAL\n')
         for rrset in self.additional:
-            print >> s, rrset.to_text(origin, relativize, **kw)
+            s.write(rrset.to_text(origin, relativize, **kw))
+            s.write(u'\n')
         #
         # We strip off the final \n so the caller can print the result without
         # doing weird things to get around eccentricities in Python print
@@ -273,7 +280,7 @@ class Message(object):
            dns.opcode.from_flags(other.flags):
             return False
         if dns.rcode.from_flags(other.flags, other.ednsflags) != \
-               dns.rcode.NOERROR:
+                dns.rcode.NOERROR:
             return True
         if dns.opcode.is_update(self.flags):
             return True
@@ -327,9 +334,9 @@ class Message(object):
         key = (self.section_number(section),
                name, rdclass, rdtype, covers, deleting)
         if not force_unique:
-            if not self.index is None:
+            if self.index is not None:
                 rrset = self.index.get(key)
-                if not rrset is None:
+                if rrset is not None:
                     return rrset
             else:
                 for rrset in section:
@@ -339,7 +346,7 @@ class Message(object):
             raise KeyError
         rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
         section.append(rrset)
-        if not self.index is None:
+        if self.index is not None:
             self.index[key] = rrset
         return rrset
 
@@ -416,7 +423,7 @@ class Message(object):
         for rrset in self.additional:
             r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
         r.write_header()
-        if not self.keyname is None:
+        if self.keyname is not None:
             r.add_tsig(self.keyname, self.keyring[self.keyname],
                        self.fudge, self.original_id, self.tsig_error,
                        self.other_data, self.request_mac,
@@ -455,7 +462,7 @@ class Message(object):
         if keyname is None:
             self.keyname = self.keyring.keys()[0]
         else:
-            if isinstance(keyname, (str, unicode)):
+            if isinstance(keyname, string_types):
                 keyname = dns.name.from_text(keyname)
             self.keyname = keyname
         self.keyalgorithm = algorithm
@@ -467,7 +474,8 @@ class Message(object):
         self.tsig_error = tsig_error
         self.other_data = other_data
 
-    def use_edns(self, edns=0, ednsflags=0, payload=1280, request_payload=None, options=None):
+    def use_edns(self, edns=0, ednsflags=0, payload=1280, request_payload=None,
+                 options=None):
         """Configure EDNS behavior.
         @param edns: The EDNS level to use.  Specifying None, False, or -1
         means 'do not use EDNS', and in this case the other parameters are
@@ -499,7 +507,7 @@ class Message(object):
             options = []
         else:
             # make sure the EDNS version in ednsflags agrees with edns
-            ednsflags &= 0xFF00FFFFL
+            ednsflags &= long(0xFF00FFFF)
             ednsflags |= (edns << 16)
             if options is None:
                 options = []
@@ -537,7 +545,7 @@ class Message(object):
         (value, evalue) = dns.rcode.to_flags(rcode)
         self.flags &= 0xFFF0
         self.flags |= value
-        self.ednsflags &= 0x00FFFFFFL
+        self.ednsflags &= long(0x00FFFFFF)
         self.ednsflags |= evalue
         if self.ednsflags != 0 and self.edns < 0:
             self.edns = 0
@@ -556,7 +564,9 @@ class Message(object):
         self.flags &= 0x87FF
         self.flags |= dns.opcode.to_flags(opcode)
 
+
 class _WireReader(object):
+
     """Wire format reader.
 
     @ivar wire: the wire-format message.
@@ -600,12 +610,12 @@ class _WireReader(object):
 
         for i in xrange(0, qcount):
             (qname, used) = dns.name.from_wire(self.wire, self.current)
-            if not self.message.origin is None:
+            if self.message.origin is not None:
                 qname = qname.relativize(self.message.origin)
             self.current = self.current + used
             (rdtype, rdclass) = \
-                     struct.unpack('!HH',
-                                   self.wire[self.current:self.current + 4])
+                struct.unpack('!HH',
+                              self.wire[self.current:self.current + 4])
             self.current = self.current + 4
             self.message.find_rrset(self.message.question, qname,
                                     rdclass, rdtype, create=True,
@@ -630,15 +640,15 @@ class _WireReader(object):
             rr_start = self.current
             (name, used) = dns.name.from_wire(self.wire, self.current)
             absolute_name = name
-            if not self.message.origin is None:
+            if self.message.origin is not None:
                 name = name.relativize(self.message.origin)
             self.current = self.current + used
             (rdtype, rdclass, ttl, rdlen) = \
-                     struct.unpack('!HHIH',
-                                   self.wire[self.current:self.current + 10])
+                struct.unpack('!HHIH',
+                              self.wire[self.current:self.current + 10])
             self.current = self.current + 10
             if rdtype == dns.rdatatype.OPT:
-                if not section is self.message.additional or seen_opt:
+                if section is not self.message.additional or seen_opt:
                     raise BadEDNS
                 self.message.payload = rdclass
                 self.message.ednsflags = ttl
@@ -648,10 +658,11 @@ class _WireReader(object):
                 optslen = rdlen
                 while optslen > 0:
                     (otype, olen) = \
-                            struct.unpack('!HH',
-                                          self.wire[current:current + 4])
+                        struct.unpack('!HH',
+                                      self.wire[current:current + 4])
                     current = current + 4
-                    opt = dns.edns.option_from_wire(otype, self.wire, current, olen)
+                    opt = dns.edns.option_from_wire(
+                        otype, self.wire, current, olen)
                     self.message.options.append(opt)
                     current = current + olen
                     optslen = optslen - 4 - olen
@@ -670,31 +681,31 @@ class _WireReader(object):
                     dns.tsig.get_algorithm_and_mac(self.wire, self.current,
                                                    rdlen)
                 self.message.tsig_ctx = \
-                                      dns.tsig.validate(self.wire,
-                                          absolute_name,
-                                          secret,
-                                          int(time.time()),
-                                          self.message.request_mac,
-                                          rr_start,
-                                          self.current,
-                                          rdlen,
-                                          self.message.tsig_ctx,
-                                          self.message.multi,
-                                          self.message.first)
+                    dns.tsig.validate(self.wire,
+                                      absolute_name,
+                                      secret,
+                                      int(time.time()),
+                                      self.message.request_mac,
+                                      rr_start,
+                                      self.current,
+                                      rdlen,
+                                      self.message.tsig_ctx,
+                                      self.message.multi,
+                                      self.message.first)
                 self.message.had_tsig = True
             else:
                 if ttl < 0:
                     ttl = 0
                 if self.updating and \
                    (rdclass == dns.rdataclass.ANY or
-                    rdclass == dns.rdataclass.NONE):
+                        rdclass == dns.rdataclass.NONE):
                     deleting = rdclass
                     rdclass = self.zone_rdclass
                 else:
                     deleting = None
                 if deleting == dns.rdataclass.ANY or \
-                   (deleting == dns.rdataclass.NONE and \
-                    section is self.message.answer):
+                   (deleting == dns.rdataclass.NONE and
+                        section is self.message.answer):
                     covers = dns.rdatatype.NONE
                     rd = None
                 else:
@@ -707,7 +718,7 @@ class _WireReader(object):
                 rrset = self.message.find_rrset(section, name,
                                                 rdclass, rdtype, covers,
                                                 deleting, True, force_unique)
-                if not rd is None:
+                if rd is not None:
                     rrset.add(rd, ttl)
             self.current = self.current + rdlen
 
@@ -732,14 +743,14 @@ class _WireReader(object):
         if not self.ignore_trailing and self.current != l:
             raise TrailingJunk
         if self.message.multi and self.message.tsig_ctx and \
-               not self.message.had_tsig:
+                not self.message.had_tsig:
             self.message.tsig_ctx.update(self.wire)
 
 
 def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
-              tsig_ctx = None, multi = False, first = True,
-              question_only = False, one_rr_per_rrset = False,
-              ignore_trailing = False):
+              tsig_ctx=None, multi=False, first=True,
+              question_only=False, one_rr_per_rrset=False,
+              ignore_trailing=False):
     """Convert a DNS wire format message into a message
     object.
 
@@ -793,6 +804,7 @@ def from_wire(wire, keyring=None, reques
 
 
 class _TextReader(object):
+
     """Text format reader.
 
     @ivar tok: the tokenizer
@@ -830,13 +842,13 @@ class _TextReader(object):
                     self.tok.unget(token)
                     break
                 self.message.flags = self.message.flags | \
-                                     dns.flags.from_text(token.value)
+                    dns.flags.from_text(token.value)
             if dns.opcode.is_update(self.message.flags):
                 self.updating = True
         elif what == 'edns':
             self.message.edns = self.tok.get_int()
             self.message.ednsflags = self.message.ednsflags | \
-                                     (self.message.edns << 16)
+                (self.message.edns << 16)
         elif what == 'eflags':
             if self.message.edns < 0:
                 self.message.edns = 0
@@ -846,7 +858,7 @@ class _TextReader(object):
                     self.tok.unget(token)
                     break
                 self.message.ednsflags = self.message.ednsflags | \
-                              dns.flags.edns_from_text(token.value)
+                    dns.flags.edns_from_text(token.value)
         elif what == 'payload':
             self.message.payload = self.tok.get_int()
             if self.message.edns < 0:
@@ -854,7 +866,7 @@ class _TextReader(object):
         elif what == 'opcode':
             text = self.tok.get_string()
             self.message.flags = self.message.flags | \
-                      dns.opcode.to_flags(dns.opcode.from_text(text))
+                dns.opcode.to_flags(dns.opcode.from_text(text))
         elif what == 'rcode':
             text = self.tok.get_string()
             self.message.set_rcode(dns.rcode.from_text(text))
@@ -865,7 +877,7 @@ class _TextReader(object):
     def _question_line(self, section):
         """Process one line from the text format question section."""
 
-        token = self.tok.get(want_leading = True)
+        token = self.tok.get(want_leading=True)
         if not token.is_whitespace():
             self.last_name = dns.name.from_text(token.value, None)
         name = self.last_name
@@ -898,7 +910,7 @@ class _TextReader(object):
 
         deleting = None
         # Name
-        token = self.tok.get(want_leading = True)
+        token = self.tok.get(want_leading=True)
         if not token.is_whitespace():
             self.last_name = dns.name.from_text(token.value, None)
         name = self.last_name
@@ -941,7 +953,7 @@ class _TextReader(object):
         rrset = self.message.find_rrset(section, name,
                                         rdclass, rdtype, covers,
                                         deleting, True, self.updating)
-        if not rd is None:
+        if rd is not None:
             rrset.add(rd, ttl)
 
     def read(self):
@@ -996,6 +1008,7 @@ def from_text(text):
 
     return m
 
+
 def from_file(f):
     """Read the next text format message from the specified file.
 
@@ -1005,15 +1018,11 @@ def from_file(f):
     @raises dns.exception.SyntaxError:
     @rtype: dns.message.Message object"""
 
-    if sys.hexversion >= 0x02030000:
-        # allow Unicode filenames; turn on universal newline support
-        str_type = basestring
-        opts = 'rU'
-    else:
-        str_type = str
-        opts = 'r'
+    str_type = string_types
+    opts = 'rU'
+
     if isinstance(f, str_type):
-        f = file(f, opts)
+        f = open(f, opts)
         want_close = True
     else:
         want_close = False
@@ -1025,7 +1034,8 @@ def from_file(f):
             f.close()
     return m
 
-def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
+
+def make_query(qname, rdtype, rdclass=dns.rdataclass.IN, use_edns=None,
                want_dnssec=False, ednsflags=0, payload=1280,
                request_payload=None, options=None):
     """Make a query message.
@@ -1061,11 +1071,11 @@ def make_query(qname, rdtype, rdclass =
     @see: RFC 2671
     @rtype: dns.message.Message object"""
 
-    if isinstance(qname, (str, unicode)):
+    if isinstance(qname, string_types):
         qname = dns.name.from_text(qname)
-    if isinstance(rdtype, (str, unicode)):
+    if isinstance(rdtype, string_types):
         rdtype = dns.rdatatype.from_text(rdtype)
-    if isinstance(rdclass, (str, unicode)):
+    if isinstance(rdclass, string_types):
         rdclass = dns.rdataclass.from_text(rdclass)
     m = Message()
     m.flags |= dns.flags.RD
@@ -1075,6 +1085,7 @@ def make_query(qname, rdtype, rdclass =
     m.want_dnssec(want_dnssec)
     return m
 
+
 def make_response(query, recursion_available=False, our_payload=8192,
                   fudge=300):
     """Make a message which is a response for the specified query.
Index: dnspython-1.12.0/dns/name.py
===================================================================
--- dnspython-1.12.0.orig/dns/name.py
+++ dnspython-1.12.0/dns/name.py
@@ -21,17 +21,23 @@
 @type empty: dns.name.Name object
 """
 
-import cStringIO
+from io import BytesIO
 import struct
 import sys
 import copy
 
-if sys.hexversion >= 0x02030000:
-    import encodings.idna
+import encodings.idna
 
 import dns.exception
 import dns.wiredata
 
+from ._compat import long, binary_type, text_type
+
+try:
+    maxint = sys.maxint
+except:
+    maxint = (1 << (8 * struct.calcsize("P"))) / 2 - 1
+
 NAMERELN_NONE = 0
 NAMERELN_SUPERDOMAIN = 1
 NAMERELN_SUBDOMAIN = 2
@@ -77,16 +83,7 @@ class NoParent(dns.exception.DNSExceptio
     or the empty name."""
     pass
 
-_escaped = {
-    '"' : True,
-    '(' : True,
-    ')' : True,
-    '.' : True,
-    ';' : True,
-    '\\' : True,
-    '@' : True,
-    '$' : True
-    }
+_escaped = bytearray(b'"().;\\@$')
 
 def _escapify(label, unicode_mode=False):
     """Escape the characters in label which need it.
@@ -94,24 +91,38 @@ def _escapify(label, unicode_mode=False)
     characters
     @returns: the escaped string
     @rtype: string"""
-    text = ''
+    if not unicode_mode:
+        text = ''
+        if isinstance(label, text_type):
+            label = label.encode()
+        for c in bytearray(label):
+            packed = struct.pack('!B', c).decode()
+            if c in _escaped:
+                text += '\\' + packed
+            elif c > 0x20 and c < 0x7F:
+                text += packed
+            else:
+                text += '\\%03d' % c
+        return text.encode()
+
+    text = u''
+    if isinstance(label, binary_type):
+        label = label.decode()
     for c in label:
-        if c in _escaped:
-            text += '\\' + c
-        elif ord(c) > 0x20 and ord(c) < 0x7F:
+        if c > u'\x20' and c < u'\x7f':
             text += c
         else:
-            if unicode_mode and ord(c) >= 0x7F:
+            if c >= u'\x7f':
                 text += c
             else:
-                text += '\\%03d' % ord(c)
+                text += u'\\%03d' % c
     return text
 
+
 def _validate_labels(labels):
     """Check for empty labels in the middle of a label sequence,
     labels that are too long, and for too many labels.
     @raises NameTooLong: the name as a whole is too long
-    @raises LabelTooLong: an individual label is too long
     @raises EmptyLabel: a label is empty (i.e. the root label) and appears
     in a position other than the end of the label sequence"""
 
@@ -124,7 +135,7 @@ def _validate_labels(labels):
         total += ll + 1
         if ll > 63:
             raise LabelTooLong
-        if i < 0 and label == '':
+        if i < 0 and label == b'':
             i = j
         j += 1
     if total > 255:
@@ -132,7 +143,17 @@ def _validate_labels(labels):
     if i >= 0 and i != l - 1:
         raise EmptyLabel
 
+
+def _ensure_bytes(label):
+    if isinstance(label, binary_type):
+        return label
+    if isinstance(label, text_type):
+        return label.encode()
+    raise ValueError
+
+
 class Name(object):
+
     """A DNS name.
 
     The dns.name.Name class represents a DNS name as a tuple of labels.
@@ -148,7 +169,7 @@ class Name(object):
         @param labels: the labels
         @type labels: any iterable whose values are strings
         """
-
+        labels = [_ensure_bytes(x) for x in labels]
         super(Name, self).__setattr__('labels', tuple(labels))
         _validate_labels(self.labels)
 
@@ -166,25 +187,25 @@ class Name(object):
         @rtype: bool
         """
 
-        return len(self.labels) > 0 and self.labels[-1] == ''
+        return len(self.labels) > 0 and self.labels[-1] == b''
 
     def is_wild(self):
         """Is this name wild?  (I.e. Is the least significant label '*'?)
         @rtype: bool
         """
 
-        return len(self.labels) > 0 and self.labels[0] == '*'
+        return len(self.labels) > 0 and self.labels[0] == b'*'
 
     def __hash__(self):
         """Return a case-insensitive hash of the name.
         @rtype: int
         """
 
-        h = 0L
+        h = long(0)
         for label in self.labels:
-            for c in label:
-                h += ( h << 3 ) + ord(c.lower())
-        return int(h % sys.maxint)
+            for c in bytearray(label.lower()):
+                h += (h << 3) + c
+        return int(h % maxint)
 
     def fullcompare(self, other):
         """Compare two names, returning a 3-tuple (relation, order, nlabels).
@@ -319,9 +340,9 @@ class Name(object):
         return '<DNS name ' + self.__str__() + '>'
 
     def __str__(self):
-        return self.to_text(False)
+        return self.to_text(False).decode()
 
-    def to_text(self, omit_final_dot = False):
+    def to_text(self, omit_final_dot=False):
         """Convert name to text format.
         @param omit_final_dot: If True, don't emit the final dot (denoting the
         root label) for absolute names.  The default is False.
@@ -329,17 +350,17 @@ class Name(object):
         """
 
         if len(self.labels) == 0:
-            return '@'
-        if len(self.labels) == 1 and self.labels[0] == '':
-            return '.'
+            return b'@'
+        if len(self.labels) == 1 and self.labels[0] == b'':
+            return b'.'
         if omit_final_dot and self.is_absolute():
             l = self.labels[:-1]
         else:
             l = self.labels
-        s = '.'.join(map(_escapify, l))
+        s = b'.'.join(map(_escapify, l))
         return s
 
-    def to_unicode(self, omit_final_dot = False):
+    def to_unicode(self, omit_final_dot=False):
         """Convert name to Unicode text format.
 
         IDN ACE lables are converted to Unicode.
@@ -357,7 +378,8 @@ class Name(object):
             l = self.labels[:-1]
         else:
             l = self.labels
-        s = u'.'.join([_escapify(encodings.idna.ToUnicode(x), True) for x in l])
+        s = u'.'.join([_escapify(encodings.idna.ToUnicode(x), True)
+                      for x in l])
         return s
 
     def to_digestable(self, origin=None):
@@ -381,14 +403,15 @@ class Name(object):
             labels.extend(list(origin.labels))
         else:
             labels = self.labels
-        dlabels = ["%s%s" % (chr(len(x)), x.lower()) for x in labels]
-        return ''.join(dlabels)
+        dlabels = [struct.pack('!B%ds' % len(x), len(x), x.lower())
+                   for x in labels]
+        return b''.join(dlabels)
 
-    def to_wire(self, file = None, compress = None, origin = None):
+    def to_wire(self, file=None, compress=None, origin=None):
         """Convert name to wire format, possibly compressing it.
 
         @param file: the file where the name is emitted (typically
-        a cStringIO file).  If None, a string containing the wire name
+        a BytesIO file).  If None, a string containing the wire name
         will be returned.
         @type file: file or None
         @param compress: The compression table.  If None (the default) names
@@ -403,7 +426,7 @@ class Name(object):
         """
 
         if file is None:
-            file = cStringIO.StringIO()
+            file = BytesIO()
             want_return = True
         else:
             want_return = False
@@ -419,22 +442,22 @@ class Name(object):
         for label in labels:
             n = Name(labels[i:])
             i += 1
-            if not compress is None:
+            if compress is not None:
                 pos = compress.get(n)
             else:
                 pos = None
-            if not pos is None:
+            if pos is not None:
                 value = 0xc000 + pos
                 s = struct.pack('!H', value)
                 file.write(s)
                 break
             else:
-                if not compress is None and len(n) > 1:
+                if compress is not None and len(n) > 1:
                     pos = file.tell()
                     if pos <= 0x3fff:
                         compress[n] = pos
                 l = len(label)
-                file.write(chr(l))
+                file.write(struct.pack('!B', l))
                 if l > 0:
                     file.write(label)
         if want_return:
@@ -476,8 +499,9 @@ class Name(object):
         elif depth == l:
             return (dns.name.empty, self)
         elif depth < 0 or depth > l:
-            raise ValueError('depth must be >= 0 and <= the length of the name')
-        return (Name(self[: -depth]), Name(self[-depth :]))
+            raise ValueError(
+                'depth must be >= 0 and <= the length of the name')
+        return (Name(self[: -depth]), Name(self[-depth:]))
 
     def concatenate(self, other):
         """Return a new name which is the concatenation of self and other.
@@ -498,7 +522,7 @@ class Name(object):
         @rtype: dns.name.Name object
         """
 
-        if not origin is None and self.is_subdomain(origin):
+        if origin is not None and self.is_subdomain(origin):
             return Name(self[: -len(origin)])
         else:
             return self
@@ -540,10 +564,11 @@ class Name(object):
             raise NoParent
         return Name(self.labels[1:])
 
-root = Name([''])
+root = Name([b''])
 empty = Name([])
 
-def from_unicode(text, origin = root):
+
+def from_unicode(text, origin=root):
     """Convert unicode text into a Name object.
 
     Lables are encoded in IDN ACE form.
@@ -551,7 +576,7 @@ def from_unicode(text, origin = root):
     @rtype: dns.name.Name object
     """
 
-    if not isinstance(text, unicode):
+    if not isinstance(text, text_type):
         raise ValueError("input to from_unicode() must be a unicode string")
     if not (origin is None or isinstance(origin, Name)):
         raise ValueError("origin must be a Name or None")
@@ -564,7 +589,7 @@ def from_unicode(text, origin = root):
         text = u''
     if text:
         if text == u'.':
-            return Name([''])	# no Unicode "u" on this constant!
+            return Name([b''])	# no Unicode "u" on this constant!
         for c in text:
             if escaping:
                 if edigits == 0:
@@ -583,8 +608,7 @@ def from_unicode(text, origin = root):
                     if edigits == 3:
                         escaping = False
                         label += chr(total)
-            elif c == u'.' or c == u'\u3002' or \
-                 c == u'\uff0e' or c == u'\uff61':
+            elif c in [u'.', u'\u3002', u'\uff0e', u'\uff61']:
                 if len(label) == 0:
                     raise EmptyLabel
                 labels.append(encodings.idna.ToASCII(label))
@@ -600,72 +624,75 @@ def from_unicode(text, origin = root):
         if len(label) > 0:
             labels.append(encodings.idna.ToASCII(label))
         else:
-            labels.append('')
-    if (len(labels) == 0 or labels[-1] != '') and not origin is None:
+            labels.append(b'')
+
+    if (len(labels) == 0 or labels[-1] != b'') and origin is not None:
         labels.extend(list(origin.labels))
     return Name(labels)
 
-def from_text(text, origin = root):
+
+def from_text(text, origin=root):
     """Convert text into a Name object.
     @rtype: dns.name.Name object
     """
 
-    if not isinstance(text, str):
-        if isinstance(text, unicode) and sys.hexversion >= 0x02030000:
-            return from_unicode(text, origin)
-        else:
-            raise ValueError("input to from_text() must be a string")
+    if isinstance(text, text_type):
+        return from_unicode(text, origin)
+    if not isinstance(text, binary_type):
+        raise ValueError("input to from_text() must be a string")
     if not (origin is None or isinstance(origin, Name)):
         raise ValueError("origin must be a Name or None")
     labels = []
-    label = ''
+    label = b''
     escaping = False
     edigits = 0
     total = 0
-    if text == '@':
-        text = ''
+    if text == b'@':
+        text = b''
     if text:
-        if text == '.':
-            return Name([''])
-        for c in text:
+        if text == b'.':
+            return Name([b''])
+        for c in bytearray(text):
+            byte_ = struct.pack('!B', c)
             if escaping:
                 if edigits == 0:
-                    if c.isdigit():
-                        total = int(c)
+                    if byte_.isdigit():
+                        total = int(byte_)
                         edigits += 1
                     else:
-                        label += c
+                        label += byte_
                         escaping = False
                 else:
-                    if not c.isdigit():
+                    if not byte_.isdigit():
                         raise BadEscape
                     total *= 10
-                    total += int(c)
+                    total += int(byte_)
                     edigits += 1
                     if edigits == 3:
                         escaping = False
-                        label += chr(total)
-            elif c == '.':
+                        label += struct.pack('!B', total)
+            elif byte_ == b'.':
                 if len(label) == 0:
                     raise EmptyLabel
                 labels.append(label)
-                label = ''
-            elif c == '\\':
+                label = b''
+            elif byte_ == b'\\':
                 escaping = True
                 edigits = 0
                 total = 0
             else:
-                label += c
+                label += byte_
         if escaping:
             raise BadEscape
         if len(label) > 0:
             labels.append(label)
         else:
-            labels.append('')
-    if (len(labels) == 0 or labels[-1] != '') and not origin is None:
+            labels.append(b'')
+    if (len(labels) == 0 or labels[-1] != b'') and origin is not None:
         labels.extend(list(origin.labels))
     return Name(labels)
 
+
 def from_wire(message, current):
     """Convert possibly compressed wire format into a Name.
     @param message: the entire DNS message
@@ -681,23 +708,23 @@ def from_wire(message, current):
     @rtype: (dns.name.Name object, int) tuple
     """
 
-    if not isinstance(message, str):
+    if not isinstance(message, binary_type):
         raise ValueError("input to from_wire() must be a byte string")
     message = dns.wiredata.maybe_wrap(message)
     labels = []
     biggest_pointer = current
     hops = 0
-    count = ord(message[current])
+    count = message[current]
     current += 1
     cused = 1
     while count != 0:
         if count < 64:
-            labels.append(message[current : current + count].unwrap())
+            labels.append(message[current: current + count].unwrap())
             current += count
             if hops == 0:
                 cused += count
         elif count >= 192:
-            current = (count & 0x3f) * 256 + ord(message[current])
+            current = (count & 0x3f) * 256 + message[current]
             if hops == 0:
                 cused += 1
             if current >= biggest_pointer:
@@ -706,7 +733,7 @@ def from_wire(message, current):
             hops += 1
         else:
             raise BadLabelType
-        count = ord(message[current])
+        count = message[current]
         current += 1
         if hops == 0:
             cused += 1
Index: dnspython-1.12.0/dns/namedict.py
===================================================================
--- dnspython-1.12.0.orig/dns/namedict.py
+++ dnspython-1.12.0/dns/namedict.py
@@ -16,6 +16,7 @@
 """DNS name dictionary"""
 
 import dns.name
+from ._compat import xrange
 
 class NameDict(dict):
 
@@ -53,7 +54,10 @@ class NameDict(dict):
             depth = self.max_depth
         for i in xrange(-depth, 0):
             n = dns.name.Name(name[i:])
-            if self.has_key(n):
+            if n in self:
                 return (n, self[n])
         v = self[dns.name.empty]
         return (dns.name.empty, v)
+
+    def has_key(self, key):
+        return key in self
Index: dnspython-1.12.0/dns/node.py
===================================================================
--- dnspython-1.12.0.orig/dns/node.py
+++ dnspython-1.12.0/dns/node.py
@@ -15,13 +15,15 @@
 
 """DNS nodes.  A node is a set of rdatasets."""
 
-import StringIO
+from io import StringIO
 
 import dns.rdataset
 import dns.rdatatype
 import dns.renderer
 
+
 class Node(object):
+
     """A DNS node.
 
     A node is a set of rdatasets
@@ -35,7 +37,7 @@ class Node(object):
         """Initialize a DNS node.
         """
 
-        self.rdatasets = [];
+        self.rdatasets = []
 
     def to_text(self, name, **kw):
         """Convert a node to text format.
@@ -47,10 +49,11 @@ class Node(object):
         @rtype: string
         """
 
-        s = StringIO.StringIO()
+        s = StringIO()
         for rds in self.rdatasets:
             if len(rds) > 0:
-                print >> s, rds.to_text(name, **kw)
+                s.write(rds.to_text(name, **kw))
+                s.write(u'\n')
         return s.getvalue()[:-1]
 
     def __repr__(self):
@@ -155,7 +158,7 @@ class Node(object):
         """
 
         rds = self.get_rdataset(rdclass, rdtype, covers)
-        if not rds is None:
+        if rds is not None:
             self.rdatasets.remove(rds)
 
     def replace_rdataset(self, replacement):
@@ -169,7 +172,7 @@ class Node(object):
         """
 
         if not isinstance(replacement, dns.rdataset.Rdataset):
-            raise ValueError, 'replacement is not an rdataset'
+            raise ValueError('replacement is not an rdataset')
         self.delete_rdataset(replacement.rdclass, replacement.rdtype,
                              replacement.covers)
         self.rdatasets.append(replacement)
Index: dnspython-1.12.0/dns/opcode.py
===================================================================
--- dnspython-1.12.0.orig/dns/opcode.py
+++ dnspython-1.12.0/dns/opcode.py
@@ -35,7 +35,7 @@ _by_text = {
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be true inverse.
 
-_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
+_by_value = dict((y, x) for x, y in _by_text.items())
 
 
 class UnknownOpcode(dns.exception.DNSException):
@@ -60,23 +60,26 @@ def from_text(text):
         raise UnknownOpcode
     return value
 
+
 def from_flags(flags):
     """Extract an opcode from DNS message flags.
 
     @param flags: int
     @rtype: int
     """
-    
+
     return (flags & 0x7800) >> 11
 
+
 def to_flags(value):
     """Convert an opcode to a value suitable for ORing into DNS message
     flags.
     @rtype: int
     """
-    
+
     return (value << 11) & 0x7800
-    
+
+
 def to_text(value):
     """Convert an opcode to text.
 
@@ -85,12 +88,13 @@ def to_text(value):
     @raises UnknownOpcode: the opcode is unknown
     @rtype: string
     """
-    
+
     text = _by_value.get(value)
     if text is None:
         text = str(value)
     return text
 
+
 def is_update(flags):
     """True if the opcode in flags is UPDATE.
 
@@ -98,7 +102,7 @@ def is_update(flags):
     @type flags: int
     @rtype: bool
     """
-    
+
     if (from_flags(flags) == UPDATE):
         return True
     return False
Index: dnspython-1.12.0/dns/query.py
===================================================================
--- dnspython-1.12.0.orig/dns/query.py
+++ dnspython-1.12.0/dns/query.py
@@ -31,6 +31,13 @@ import dns.message
 import dns.rdataclass
 import dns.rdatatype
 
+from ._compat import long, string_types
+
+if sys.version_info > (3,):
+    select_error = OSError
+else:
+    select_error = select.error
+
 class UnexpectedSource(dns.exception.DNSException):
     """Raised if a query response comes from an unexpected address or port."""
     pass
@@ -75,6 +82,7 @@ def _poll_for(fd, readable, writable, er
 
     return bool(event_list)
 
+
 def _select_for(fd, readable, writable, error, timeout):
     """Select polling backend.
     @param fd: File descriptor
@@ -103,6 +111,7 @@ def _select_for(fd, readable, writable,
 
     return bool((rcount or wcount or xcount))
 
+
 def _wait_for(fd, readable, writable, error, expiration):
     done = False
     while not done:
@@ -115,11 +124,12 @@ def _wait_for(fd, readable, writable, er
         try:
             if not _polling_backend(fd, readable, writable, error, timeout):
                 raise dns.exception.Timeout
-        except select.error, e:
+        except select_error as e:
             if e.args[0] != errno.EINTR:
                 raise e
         done = True
 
+
 def _set_polling_backend(fn):
     """
     Internal API. Do not use.
@@ -136,12 +146,15 @@ if hasattr(select, 'poll'):
 else:
     _polling_backend = _select_for
 
+
 def _wait_for_readable(s, expiration):
     _wait_for(s, True, False, True, expiration)
 
+
 def _wait_for_writable(s, expiration):
     _wait_for(s, False, True, True, expiration)
 
+
 def _addresses_equal(af, a1, a2):
     # Convert the first value of the tuple, which is a textual format
     # address into binary form, so that we are not confused by different
@@ -150,6 +163,7 @@ def _addresses_equal(af, a1, a2):
     n2 = dns.inet.inet_pton(af, a2[0])
     return n1 == n2 and a1[1:] == a2[1:]
 
+
 def _destination_and_source(af, where, port, source, source_port):
     # Apply defaults and compute destination and source tuples
     # suitable for use in connect(), sendto(), or bind().
@@ -172,6 +186,7 @@ def _destination_and_source(af, where, p
             source = (source, source_port, 0, 0)
     return (af, destination, source)
 
+
 def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         ignore_unexpected=False, one_rr_per_rrset=False):
     """Return the response obtained after sending a query via UDP.
@@ -203,8 +218,8 @@ def udp(q, where, timeout=None, port=53,
     """
 
     wire = q.to_wire()
-    (af, destination, source) = _destination_and_source(af, where, port, source,
-                                                        source_port)
+    (af, destination, source) = _destination_and_source(af, where, port,
+                                                        source, source_port)
     s = socket.socket(af, socket.SOCK_DGRAM, 0)
     try:
         expiration = _compute_expiration(timeout)
@@ -217,8 +232,8 @@ def udp(q, where, timeout=None, port=53,
             _wait_for_readable(s, expiration)
             (wire, from_address) = s.recvfrom(65535)
             if _addresses_equal(af, from_address, destination) or \
-                    (dns.inet.is_multicast(where) and \
-                         from_address[1:] == destination[1:]):
+                    (dns.inet.is_multicast(where) and
+                     from_address[1:] == destination[1:]):
                 break
             if not ignore_unexpected:
                 raise UnexpectedSource('got a response from '
@@ -232,6 +247,7 @@ def udp(q, where, timeout=None, port=53,
         raise BadResponse
     return r
 
+
 def _net_read(sock, count, expiration):
     """Read the specified number of bytes from sock.  Keep trying until we
     either get the desired amount, or we hit EOF.
@@ -248,6 +264,7 @@ def _net_read(sock, count, expiration):
         s = s + n
     return s
 
+
 def _net_write(sock, data, expiration):
     """Write the specified data to the socket.
     A Timeout exception will be raised if the operation is not completed
@@ -259,16 +276,18 @@ def _net_write(sock, data, expiration):
         _wait_for_writable(sock, expiration)
         current += sock.send(data[current:])
 
+
 def _connect(s, address):
     try:
         s.connect(address)
     except socket.error:
         (ty, v) = sys.exc_info()[:2]
         if v[0] != errno.EINPROGRESS and \
-               v[0] != errno.EWOULDBLOCK and \
-               v[0] != errno.EALREADY:
+            v[0] != errno.EWOULDBLOCK and \
+                v[0] != errno.EALREADY:
             raise v
 
+
 def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         one_rr_per_rrset=False):
     """Return the response obtained after sending a query via TCP.
@@ -297,8 +316,8 @@ def tcp(q, where, timeout=None, port=53,
     """
 
     wire = q.to_wire()
-    (af, destination, source) = _destination_and_source(af, where, port, source,
-                                                        source_port)
+    (af, destination, source) = _destination_and_source(af, where, port,
+                                                        source, source_port)
     s = socket.socket(af, socket.SOCK_STREAM, 0)
     try:
         expiration = _compute_expiration(timeout)
@@ -325,6 +344,7 @@ def tcp(q, where, timeout=None, port=53,
         raise BadResponse
     return r
 
+
 def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         timeout=None, port=53, keyring=None, keyname=None, relativize=True,
         af=None, lifetime=None, source=None, source_port=0, serial=0,
@@ -378,20 +398,20 @@ def xfr(where, zone, rdtype=dns.rdatatyp
     @type keyalgorithm: string
     """
 
-    if isinstance(zone, (str, unicode)):
+    if isinstance(zone, string_types):
         zone = dns.name.from_text(zone)
-    if isinstance(rdtype, (str, unicode)):
+    if isinstance(rdtype, string_types):
         rdtype = dns.rdatatype.from_text(rdtype)
     q = dns.message.make_query(zone, rdtype, rdclass)
     if rdtype == dns.rdatatype.IXFR:
         rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA',
                                     '. . %u 0 0 0 0' % serial)
         q.authority.append(rrset)
-    if not keyring is None:
+    if keyring is not None:
         q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
     wire = q.to_wire()
-    (af, destination, source) = _destination_and_source(af, where, port, source,
-                                                        source_port)
+    (af, destination, source) = _destination_and_source(af, where, port,
+                                                        source, source_port)
     if use_udp:
         if rdtype != dns.rdatatype.IXFR:
             raise ValueError('cannot do a UDP AXFR')
@@ -414,7 +434,6 @@ def xfr(where, zone, rdtype=dns.rdatatyp
     delete_mode = True
     expecting_SOA = False
     soa_rrset = None
-    soa_count = 0
     if relativize:
         origin = zone
         oname = dns.name.empty
@@ -434,16 +453,18 @@ def xfr(where, zone, rdtype=dns.rdatatyp
             ldata = _net_read(s, 2, mexpiration)
             (l,) = struct.unpack("!H", ldata)
             wire = _net_read(s, l, mexpiration)
+        is_ixfr = (rdtype == dns.rdatatype.IXFR)
         r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
                                   xfr=True, origin=origin, tsig_ctx=tsig_ctx,
                                   multi=True, first=first,
-                                  one_rr_per_rrset=(rdtype==dns.rdatatype.IXFR))
+                                  one_rr_per_rrset=is_ixfr)
         tsig_ctx = r.tsig_ctx
         first = False
         answer_index = 0
         if soa_rrset is None:
             if not r.answer or r.answer[0].name != oname:
-                raise dns.exception.FormError("No answer or RRset not for qname")
+                raise dns.exception.FormError(
+                    "No answer or RRset not for qname")
             rrset = r.answer[0]
             if rrset.rdtype != dns.rdatatype.SOA:
                 raise dns.exception.FormError("first RRset is not an SOA")
@@ -467,7 +488,8 @@ def xfr(where, zone, rdtype=dns.rdatatyp
             if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname:
                 if expecting_SOA:
                     if rrset[0].serial != serial:
-                        raise dns.exception.FormError("IXFR base serial mismatch")
+                        raise dns.exception.FormError(
+                            "IXFR base serial mismatch")
                     expecting_SOA = False
                 elif rdtype == dns.rdatatype.IXFR:
                     delete_mode = not delete_mode
@@ -477,8 +499,8 @@ def xfr(where, zone, rdtype=dns.rdatatyp
                 # the record in the expected part of the response.
                 #
                 if rrset == soa_rrset and \
-                        (rdtype == dns.rdatatype.AXFR or \
-                        (rdtype == dns.rdatatype.IXFR and delete_mode)):
+                        (rdtype == dns.rdatatype.AXFR or
+                         (rdtype == dns.rdatatype.IXFR and delete_mode)):
                     done = True
             elif expecting_SOA:
                 #
Index: dnspython-1.12.0/dns/rcode.py
===================================================================
--- dnspython-1.12.0.orig/dns/rcode.py
+++ dnspython-1.12.0/dns/rcode.py
@@ -16,6 +16,8 @@
 """DNS Result Codes."""
 
 import dns.exception
+from ._compat import long
+
 
 NOERROR = 0
 FORMERR = 1
@@ -49,7 +51,7 @@ _by_text = {
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be a true inverse.
 
-_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
+_by_value = dict((y, x) for x, y in _by_text.items())
 
 
 class UnknownRcode(dns.exception.DNSException):
@@ -74,6 +76,7 @@ def from_text(text):
         raise UnknownRcode
     return v
 
+
 def from_flags(flags, ednsflags):
     """Return the rcode value encoded by flags and ednsflags.
 
@@ -90,6 +93,7 @@ def from_flags(flags, ednsflags):
         raise ValueError('rcode must be >= 0 and <= 4095')
     return value
 
+
 def to_flags(value):
     """Return a (flags, ednsflags) tuple which encodes the rcode.
 
@@ -105,6 +109,7 @@ def to_flags(value):
     ev = long(value & 0xff0) << 20
     return (v, ev)
 
+
 def to_text(value):
     """Convert rcode into text.
 
Index: dnspython-1.12.0/dns/rdata.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdata.py
+++ dnspython-1.12.0/dns/rdata.py
@@ -25,7 +25,10 @@ default is 'dns.rdtypes'.  Changing this
 chunk of hexstring that _hexify() produces before whitespace occurs.
 @type _hex_chunk: int"""
 
-import cStringIO
+from io import BytesIO
+import base64
+import binascii
+import struct
 
 import dns.exception
 import dns.name
@@ -33,10 +36,14 @@ import dns.rdataclass
 import dns.rdatatype
 import dns.tokenizer
 import dns.wiredata
+from ._compat import xrange, string_types, text_type, binary_type
+
+from ._compat import xcmp
 
 _hex_chunksize = 32
 
-def _hexify(data, chunksize=None):
+
+def _hexify(data, chunksize=_hex_chunksize):
     """Convert a binary string into its hex encoding, broken up into chunks
     of I{chunksize} characters separated by a space.
 
@@ -46,22 +53,15 @@ def _hexify(data, chunksize=None):
     @rtype: string
     """
 
-    if chunksize is None:
-        chunksize = _hex_chunksize
-    hex = data.encode('hex_codec')
-    l = len(hex)
-    if l > chunksize:
-        chunks = []
-        i = 0
-        while i < l:
-            chunks.append(hex[i : i + chunksize])
-            i += chunksize
-        hex = ' '.join(chunks)
-    return hex
+    line = binascii.hexlify(data)
+    return b' '.join([line[i:i + chunksize]
+                      for i
+                      in range(0, len(line), chunksize)]).decode()
 
 _base64_chunksize = 32
 
-def _base64ify(data, chunksize=None):
+
+def _base64ify(data, chunksize=_base64_chunksize):
     """Convert a binary string into its base64 encoding, broken up into chunks
     of I{chunksize} characters separated by a space.
 
@@ -72,24 +72,16 @@ def _base64ify(data, chunksize=None):
     @rtype: string
     """
 
-    if chunksize is None:
-        chunksize = _base64_chunksize
-    b64 = data.encode('base64_codec')
-    b64 = b64.replace('\n', '')
-    l = len(b64)
-    if l > chunksize:
-        chunks = []
-        i = 0
-        while i < l:
-            chunks.append(b64[i : i + chunksize])
-            i += chunksize
-        b64 = ' '.join(chunks)
-    return b64
+    line = base64.b64encode(data)
+    return b' '.join([line[i:i + chunksize]
+                      for i
+                      in range(0, len(line), chunksize)]).decode()
 
 __escaped = {
-    '"' : True,
-    '\\' : True,
-    }
+    '"': True,
+    '\\': True,
+}
+
 
 def _escapify(qstring):
     """Escape the characters in a quoted string which need it.
@@ -100,16 +92,23 @@ def _escapify(qstring):
     @rtype: string
     """
 
+    if isinstance(qstring, text_type):
+        qstring = qstring.encode()
+    if not isinstance(qstring, bytearray):
+        qstring = bytearray(qstring)
+
     text = ''
     for c in qstring:
-        if c in __escaped:
-            text += '\\' + c
-        elif ord(c) >= 0x20 and ord(c) < 0x7F:
-            text += c
+        packed = struct.pack('!B', c).decode()
+        if packed in __escaped:
+            text += '\\' + packed
+        elif c >= 0x20 and c < 0x7F:
+            text += packed
         else:
-            text += '\\%03d' % ord(c)
+            text += '\\%03d' % c
     return text
 
+
 def _truncate_bitmap(what):
     """Determine the index of greatest byte that isn't all zeros, and
     return the bitmap that contains all the bytes less than that index.
@@ -120,11 +119,13 @@ def _truncate_bitmap(what):
     """
 
     for i in xrange(len(what) - 1, -1, -1):
-        if what[i] != '\x00':
+        if what[i] != 0:
             break
-    return ''.join(what[0 : i + 1])
+    return what[0: i + 1]
+
 
 class Rdata(object):
+
     """Base class for all DNS rdata types.
     """
 
@@ -167,17 +168,17 @@ class Rdata(object):
         """
         raise NotImplementedError
 
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         """Convert an rdata to wire format.
         @rtype: string
         """
 
         raise NotImplementedError
 
-    def to_digestable(self, origin = None):
+    def to_digestable(self, origin=None):
         """Convert rdata to a format suitable for digesting in hashes.  This
         is also the DNSSEC canonical form."""
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f, None, origin)
         return f.getvalue()
 
@@ -264,11 +265,11 @@ class Rdata(object):
         # We specifiy an arbitrary origin of '.' when doing the
         # comparison, since the rdata may have relative names and we
         # can't convert a relative name to wire without an origin.
-        b1 = cStringIO.StringIO()
+        b1 = BytesIO()
         self.to_wire(b1, None, dns.name.root)
-        b2 = cStringIO.StringIO()
+        b2 = BytesIO()
         other.to_wire(b2, None, dns.name.root)
-        return cmp(b1.getvalue(), b2.getvalue())
+        return xcmp(b1.getvalue(), b2.getvalue())
 
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         """Build an rdata object from text format.
@@ -288,9 +289,8 @@ class Rdata(object):
 
         raise NotImplementedError
 
-    from_text = classmethod(from_text)
-
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         """Build an rdata object from wire format
 
         @param rdclass: The rdata class
@@ -310,9 +310,7 @@ class Rdata(object):
 
         raise NotImplementedError
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         """Convert any domain names in the rdata to the specified
         relativization.
         """
@@ -321,6 +319,7 @@ class Rdata(object):
 
 
 class GenericRdata(Rdata):
+
     """Generate Rdata Class
 
     This class is used for rdata types for which we have no better
@@ -336,6 +335,7 @@ class GenericRdata(Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return r'\# %d ' % len(self.data) + _hexify(self.data)
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         token = tok.get()
         if not token.is_identifier() or token.value != '\#':
@@ -346,25 +346,22 @@ class GenericRdata(Rdata):
             token = tok.get()
             if token.is_eol_or_eof():
                 break
-            chunks.append(token.value)
-        hex = ''.join(chunks)
-        data = hex.decode('hex_codec')
+            chunks.append(token.value.encode())
+        hex = b''.join(chunks)
+        data = binascii.unhexlify(hex)
         if len(data) != length:
             raise dns.exception.SyntaxError('generic rdata hex data has wrong length')
         return cls(rdclass, rdtype, data)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(self.data)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         return cls(rdclass, rdtype, wire[current : current + rdlen])
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        return cmp(self.data, other.data)
+        return xcmp(self.data, other.data)
 
 _rdata_modules = {}
 _module_prefix = 'dns.rdtypes'
@@ -402,7 +399,8 @@ def get_rdata_class(rdclass, rdtype):
         cls = GenericRdata
     return cls
 
-def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
+
+def from_text(rdclass, rdtype, tok, origin=None, relativize=True):
     """Build an rdata object from text format.
 
     This function attempts to dynamically load a class which
@@ -428,7 +426,7 @@ def from_text(rdclass, rdtype, tok, orig
     @type relativize: bool
     @rtype: dns.rdata.Rdata instance"""
 
-    if isinstance(tok, str):
+    if isinstance(tok, (text_type, binary_type)):
         tok = dns.tokenizer.Tokenizer(tok)
     cls = get_rdata_class(rdclass, rdtype)
     if cls != GenericRdata:
@@ -448,7 +446,8 @@ def from_text(rdclass, rdtype, tok, orig
                              origin)
     return cls.from_text(rdclass, rdtype, tok, origin, relativize)
 
-def from_wire(rdclass, rdtype, wire, current, rdlen, origin = None):
+
+def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None):
     """Build an rdata object from wire format
 
     This function attempts to dynamically load a class which
Index: dnspython-1.12.0/dns/rdataclass.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdataclass.py
+++ dnspython-1.12.0/dns/rdataclass.py
@@ -47,7 +47,7 @@ _by_text = {
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be true inverse.
 
-_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
+_by_value = dict((y, x) for x, y in _by_text.items())
 
 # Now that we've built the inverse map, we can add class aliases to
 # the _by_text mapping.
@@ -81,13 +81,14 @@ def from_text(text):
     value = _by_text.get(text.upper())
     if value is None:
         match = _unknown_class_pattern.match(text)
-        if match == None:
+        if match is None:
             raise UnknownRdataclass
         value = int(match.group(1))
         if value < 0 or value > 65535:
             raise ValueError("class must be between >= 0 and <= 65535")
     return value
 
+
 def to_text(value):
     """Convert a DNS rdata class to text.
     @param value: the rdata class value
@@ -100,15 +101,16 @@ def to_text(value):
         raise ValueError("class must be between >= 0 and <= 65535")
     text = _by_value.get(value)
     if text is None:
-        text = 'CLASS' + `value`
+        text = 'CLASS' + repr(value)
     return text
 
+
 def is_metaclass(rdclass):
     """True if the class is a metaclass.
     @param rdclass: the rdata class
     @type rdclass: int
     @rtype: bool"""
 
-    if _metaclasses.has_key(rdclass):
+    if rdclass in _metaclasses:
         return True
     return False
Index: dnspython-1.12.0/dns/rdataset.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdataset.py
+++ dnspython-1.12.0/dns/rdataset.py
@@ -16,7 +16,7 @@
 """DNS rdatasets (an rdataset is a set of rdatas of a given type and class)"""
 
 import random
-import StringIO
+from io import StringIO
 import struct
 
 import dns.exception
@@ -24,6 +24,7 @@ import dns.rdatatype
 import dns.rdataclass
 import dns.rdata
 import dns.set
+from ._compat import string_types
 
 # define SimpleSet here for backwards compatibility
 SimpleSet = dns.set.Set
@@ -110,7 +111,7 @@ class Rdataset(dns.set.Set):
         #
         if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype:
             raise IncompatibleTypes
-        if not ttl is None:
+        if ttl is not None:
             self.update_ttl(ttl)
         if self.rdtype == dns.rdatatype.RRSIG or \
            self.rdtype == dns.rdatatype.SIG:
@@ -185,15 +186,15 @@ class Rdataset(dns.set.Set):
         @type origin: dns.name.Name object
         @param relativize: True if names should names be relativized
         @type relativize: bool"""
-        if not name is None:
+        if name is not None:
             name = name.choose_relativity(origin, relativize)
             ntext = str(name)
             pad = ' '
         else:
             ntext = ''
             pad = ''
-        s = StringIO.StringIO()
-        if not override_rdclass is None:
+        s = StringIO()
+        if override_rdclass is not None:
             rdclass = override_rdclass
         else:
             rdclass = self.rdclass
@@ -203,15 +204,16 @@ class Rdataset(dns.set.Set):
             # some dynamic updates, so we don't need to print out the TTL
             # (which is meaningless anyway).
             #
-            print >> s, '%s%s%s %s' % (ntext, pad,
-                                       dns.rdataclass.to_text(rdclass),
-                                       dns.rdatatype.to_text(self.rdtype))
+            s.write(u'%s%s%s %s\n' % (ntext, pad,
+                                      dns.rdataclass.to_text(rdclass),
+                                      dns.rdatatype.to_text(self.rdtype)))
         else:
             for rd in self:
-                print >> s, '%s%s%d %s %s %s' % \
-                      (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass),
-                       dns.rdatatype.to_text(self.rdtype),
-                       rd.to_text(origin=origin, relativize=relativize, **kw))
+                s.write(u'%s%s%d %s %s %s\n' %
+                        (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass),
+                         dns.rdatatype.to_text(self.rdtype),
+                         rd.to_text(origin=origin, relativize=relativize,
+                         **kw)))
         #
         # We strip off the final \n for the caller's convenience in printing
         #
@@ -233,8 +235,8 @@ class Rdataset(dns.set.Set):
         @rtype: int
         """
 
-        if not override_rdclass is None:
-            rdclass =  override_rdclass
+        if override_rdclass is not None:
+            rdclass = override_rdclass
             want_shuffle = False
         else:
             rdclass = self.rdclass
@@ -274,6 +276,7 @@ class Rdataset(dns.set.Set):
             return True
         return False
 
+
 def from_text_list(rdclass, rdtype, ttl, text_rdatas):
     """Create an rdataset with the specified class, type, and TTL, and with
     the specified list of rdatas in text format.
@@ -281,9 +284,9 @@ def from_text_list(rdclass, rdtype, ttl,
     @rtype: dns.rdataset.Rdataset object
     """
 
-    if isinstance(rdclass, (str, unicode)):
+    if isinstance(rdclass, string_types):
         rdclass = dns.rdataclass.from_text(rdclass)
-    if isinstance(rdtype, (str, unicode)):
+    if isinstance(rdtype, string_types):
         rdtype = dns.rdatatype.from_text(rdtype)
     r = Rdataset(rdclass, rdtype)
     r.update_ttl(ttl)
@@ -292,6 +295,7 @@ def from_text_list(rdclass, rdtype, ttl,
         r.add(rd)
     return r
 
+
 def from_text(rdclass, rdtype, ttl, *text_rdatas):
     """Create an rdataset with the specified class, type, and TTL, and with
     the specified rdatas in text format.
@@ -301,6 +305,7 @@ def from_text(rdclass, rdtype, ttl, *tex
 
     return from_text_list(rdclass, rdtype, ttl, text_rdatas)
 
+
 def from_rdata_list(ttl, rdatas):
     """Create an rdataset with the specified TTL, and with
     the specified list of rdata objects.
@@ -315,10 +320,10 @@ def from_rdata_list(ttl, rdatas):
         if r is None:
             r = Rdataset(rd.rdclass, rd.rdtype)
             r.update_ttl(ttl)
-            first_time = False
         r.add(rd)
     return r
 
+
 def from_rdata(ttl, *rdatas):
     """Create an rdataset with the specified TTL, and with
     the specified rdata objects.
Index: dnspython-1.12.0/dns/rdatatype.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdatatype.py
+++ dnspython-1.12.0/dns/rdatatype.py
@@ -160,7 +160,7 @@ _by_text = {
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be true inverse.
 
-_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
+_by_value = dict((y, x) for x, y in _by_text.items())
 
 
 _metatypes = {
@@ -192,13 +192,14 @@ def from_text(text):
     value = _by_text.get(text.upper())
     if value is None:
         match = _unknown_type_pattern.match(text)
-        if match == None:
+        if match is None:
             raise UnknownRdatatype
         value = int(match.group(1))
         if value < 0 or value > 65535:
             raise ValueError("type must be between >= 0 and <= 65535")
     return value
 
+
 def to_text(value):
     """Convert a DNS rdata type to text.
     @param value: the rdata type value
@@ -210,25 +211,27 @@ def to_text(value):
         raise ValueError("type must be between >= 0 and <= 65535")
     text = _by_value.get(value)
     if text is None:
-        text = 'TYPE' + `value`
+        text = 'TYPE' + repr(value)
     return text
 
+
 def is_metatype(rdtype):
     """True if the type is a metatype.
     @param rdtype: the type
     @type rdtype: int
     @rtype: bool"""
 
-    if rdtype >= TKEY and rdtype <= ANY or _metatypes.has_key(rdtype):
+    if rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes:
         return True
     return False
 
+
 def is_singleton(rdtype):
     """True if the type is a singleton.
     @param rdtype: the type
     @type rdtype: int
     @rtype: bool"""
 
-    if _singletons.has_key(rdtype):
+    if rdtype in _singletons:
         return True
     return False
Index: dnspython-1.12.0/dns/rdtypes/ANY/AFSDB.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/AFSDB.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/AFSDB.py
@@ -15,7 +15,9 @@
 
 import dns.rdtypes.mxbase
 
+
 class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX):
+
     """AFSDB record
 
     @ivar subtype: the subtype value
Index: dnspython-1.12.0/dns/rdtypes/ANY/CERT.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/CERT.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/CERT.py
@@ -13,43 +13,49 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
 import struct
+import base64
 
 import dns.exception
 import dns.dnssec
 import dns.rdata
 import dns.tokenizer
+from io import BytesIO
+from dns._compat import xcmp
 
 _ctype_by_value = {
-    1 : 'PKIX',
-    2 : 'SPKI',
-    3 : 'PGP',
-    253 : 'URI',
-    254 : 'OID',
-    }
+    1: 'PKIX',
+    2: 'SPKI',
+    3: 'PGP',
+    253: 'URI',
+    254: 'OID',
+}
 
 _ctype_by_name = {
-    'PKIX' : 1,
-    'SPKI' : 2,
-    'PGP' : 3,
-    'URI' : 253,
-    'OID' : 254,
-    }
+    'PKIX': 1,
+    'SPKI': 2,
+    'PGP': 3,
+    'URI': 253,
+    'OID': 254,
+}
+
 
 def _ctype_from_text(what):
     v = _ctype_by_name.get(what)
-    if not v is None:
+    if v is not None:
         return v
     return int(what)
 
+
 def _ctype_to_text(what):
     v = _ctype_by_value.get(what)
-    if not v is None:
+    if v is not None:
         return v
     return str(what)
 
+
 class CERT(dns.rdata.Rdata):
+
     """CERT record
 
     @ivar certificate_type: certificate type
@@ -78,7 +84,8 @@ class CERT(dns.rdata.Rdata):
                                 dns.dnssec.algorithm_to_text(self.algorithm),
                                 dns.rdata._base64ify(self.certificate))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         certificate_type = _ctype_from_text(tok.get_string())
         key_tag = tok.get_uint16()
         algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
@@ -91,35 +98,32 @@ class CERT(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        b64 = ''.join(chunks)
-        certificate = b64.decode('base64_codec')
+            chunks.append(t.value.encode())
+        b64 = b''.join(chunks)
+        certificate = base64.b64decode(b64)
         return cls(rdclass, rdtype, certificate_type, key_tag,
                    algorithm, certificate)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         prefix = struct.pack("!HHB", self.certificate_type, self.key_tag,
                              self.algorithm)
         file.write(prefix)
         file.write(self.certificate)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        prefix = wire[current : current + 5].unwrap()
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        prefix = wire[current: current + 5].unwrap()
         current += 5
         rdlen -= 5
         if rdlen < 0:
             raise dns.exception.FormError
         (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix)
-        certificate = wire[current : current + rdlen].unwrap()
+        certificate = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
                    certificate)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f)
         wire1 = f.getvalue()
         f.seek(0)
@@ -128,4 +132,4 @@ class CERT(dns.rdata.Rdata):
         wire2 = f.getvalue()
         f.close()
 
-        return cmp(wire1, wire2)
+        return xcmp(wire1, wire2)
Index: dnspython-1.12.0/dns/rdtypes/ANY/CNAME.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/CNAME.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/CNAME.py
@@ -15,7 +15,9 @@
 
 import dns.rdtypes.nsbase
 
+
 class CNAME(dns.rdtypes.nsbase.NSBase):
+
     """CNAME record
 
     Note: although CNAME is officially a singleton type, dnspython allows
Index: dnspython-1.12.0/dns/rdtypes/ANY/DLV.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/DLV.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/DLV.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.dsbase
 
+
 class DLV(dns.rdtypes.dsbase.DSBase):
+
     """DLV record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/DNAME.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/DNAME.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/DNAME.py
@@ -15,7 +15,10 @@
 
 import dns.rdtypes.nsbase
 
+
 class DNAME(dns.rdtypes.nsbase.UncompressedNS):
+
     """DNAME record"""
-    def to_digestable(self, origin = None):
+
+    def to_digestable(self, origin=None):
         return self.target.to_digestable(origin)
Index: dnspython-1.12.0/dns/rdtypes/ANY/DNSKEY.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/DNSKEY.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/DNSKEY.py
@@ -20,6 +20,9 @@ import dns.exception
 import dns.dnssec
 import dns.rdata
 
+import base64
+from dns._compat import xcmp
+
 
 # flag constants
 SEP = 0x0001
@@ -35,7 +38,7 @@ _flag_by_text = {
 # We construct the inverse mapping programmatically to ensure that we
 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
 # would cause the mapping not to be true inverse.
-_flag_by_value = dict([(y, x) for x, y in _flag_by_text.iteritems()])
+_flag_by_value = dict([(y, x) for x, y in _flag_by_text.items()])
 
 
 def flags_to_text_set(flags):
@@ -93,6 +96,7 @@ class DNSKEY(dns.rdata.Rdata):
         return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
                                 dns.rdata._base64ify(self.key))
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         flags = tok.get_uint16()
         protocol = tok.get_uint8()
@@ -104,18 +108,17 @@ class DNSKEY(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        b64 = ''.join(chunks)
-        key = b64.decode('base64_codec')
+            chunks.append(t.value.encode())
+        b64 = b''.join(chunks)
+        key = base64.b64decode(b64)
         return cls(rdclass, rdtype, flags, protocol, algorithm, key)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
         file.write(header)
         file.write(self.key)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         if rdlen < 4:
             raise dns.exception.FormError
@@ -126,14 +129,12 @@ class DNSKEY(dns.rdata.Rdata):
         return cls(rdclass, rdtype, header[0], header[1], header[2],
                    key)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         hs = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
         ho = struct.pack("!HBB", other.flags, other.protocol, other.algorithm)
-        v = cmp(hs, ho)
+        v = xcmp(hs, ho)
         if v == 0:
-            v = cmp(self.key, other.key)
+            v = xcmp(self.key, other.key)
         return v
 
     def flags_to_text_set(self):
Index: dnspython-1.12.0/dns/rdtypes/ANY/DS.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/DS.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/DS.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.dsbase
 
+
 class DS(dns.rdtypes.dsbase.DSBase):
+
     """DS record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/GPOS.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/GPOS.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/GPOS.py
@@ -13,24 +13,37 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import long, text_type
+from dns._compat import xcmp
+
 
 def _validate_float_string(what):
-    if what[0] == '-' or what[0] == '+':
+    if what[0] == b'-'[0] or what[0] == b'+'[0]:
         what = what[1:]
     if what.isdigit():
         return
-    (left, right) = what.split('.')
-    if left == '' and right == '':
+    (left, right) = what.split(b'.')
+    if left == b'' and right == b'':
         raise dns.exception.FormError
-    if not left == '' and not left.isdigit():
+    if not left == b'' and not left.decode().isdigit():
         raise dns.exception.FormError
-    if not right == '' and not right.isdigit():
+    if not right == b'' and not right.decode().isdigit():
         raise dns.exception.FormError
 
+
+def _sanitize(value):
+    if isinstance(value, text_type):
+        return value.encode()
+    return value
+
+
 class GPOS(dns.rdata.Rdata):
+
     """GPOS record
 
     @ivar latitude: latitude
@@ -57,6 +70,9 @@ class GPOS(dns.rdata.Rdata):
            isinstance(altitude, int) or \
            isinstance(altitude, long):
             altitude = str(altitude)
+        latitude = _sanitize(latitude)
+        longitude = _sanitize(longitude)
+        altitude = _sanitize(altitude)
         _validate_float_string(latitude)
         _validate_float_string(longitude)
         _validate_float_string(altitude)
@@ -65,8 +81,11 @@ class GPOS(dns.rdata.Rdata):
         self.altitude = altitude
 
     def to_text(self, origin=None, relativize=True, **kw):
-        return '%s %s %s' % (self.latitude, self.longitude, self.altitude)
+        return '%s %s %s' % (self.latitude.decode(),
+                             self.longitude.decode(),
+                             self.altitude.decode())
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         latitude = tok.get_string()
         longitude = tok.get_string()
@@ -74,27 +93,23 @@ class GPOS(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, latitude, longitude, altitude)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         l = len(self.latitude)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.latitude)
         l = len(self.longitude)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.longitude)
         l = len(self.altitude)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.altitude)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
@@ -102,7 +117,7 @@ class GPOS(dns.rdata.Rdata):
         latitude = wire[current : current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
@@ -110,7 +125,7 @@ class GPOS(dns.rdata.Rdata):
         longitude = wire[current : current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
@@ -118,14 +133,12 @@ class GPOS(dns.rdata.Rdata):
         altitude = wire[current : current + l].unwrap()
         return cls(rdclass, rdtype, latitude, longitude, altitude)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        v = cmp(self.latitude, other.latitude)
+        v = xcmp(self.latitude, other.latitude)
         if v == 0:
-            v = cmp(self.longitude, other.longitude)
+            v = xcmp(self.longitude, other.longitude)
             if v == 0:
-                v = cmp(self.altitude, other.altitude)
+                v = xcmp(self.altitude, other.altitude)
         return v
 
     def _get_float_latitude(self):
Index: dnspython-1.12.0/dns/rdtypes/ANY/HINFO.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/HINFO.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/HINFO.py
@@ -13,11 +13,17 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import text_type
+from dns._compat import xcmp
+
 
 class HINFO(dns.rdata.Rdata):
+
     """HINFO record
 
     @ivar cpu: the CPU type
@@ -30,35 +36,39 @@ class HINFO(dns.rdata.Rdata):
 
     def __init__(self, rdclass, rdtype, cpu, os):
         super(HINFO, self).__init__(rdclass, rdtype)
-        self.cpu = cpu
-        self.os = os
+        if isinstance(cpu, text_type):
+            self.cpu = cpu.encode()
+        else:
+            self.cpu = cpu
+        if isinstance(os, text_type):
+            self.os = os.encode()
+        else:
+            self.os = os
 
     def to_text(self, origin=None, relativize=True, **kw):
         return '"%s" "%s"' % (dns.rdata._escapify(self.cpu),
                               dns.rdata._escapify(self.os))
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         cpu = tok.get_string()
         os = tok.get_string()
         tok.get_eol()
         return cls(rdclass, rdtype, cpu, os)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         l = len(self.cpu)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.cpu)
         l = len(self.os)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.os)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
@@ -66,7 +76,7 @@ class HINFO(dns.rdata.Rdata):
         cpu = wire[current : current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
@@ -74,10 +84,8 @@ class HINFO(dns.rdata.Rdata):
         os = wire[current : current + l].unwrap()
         return cls(rdclass, rdtype, cpu, os)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        v = cmp(self.cpu, other.cpu)
+        v = xcmp(self.cpu, other.cpu)
         if v == 0:
-            v = cmp(self.os, other.os)
+            v = xcmp(self.os, other.os)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/HIP.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/HIP.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/HIP.py
@@ -13,15 +13,19 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
-import string
 import struct
+import base64
+import binascii
 
 import dns.exception
 import dns.rdata
 import dns.rdatatype
+from io import BytesIO
+from dns._compat import xcmp
+
 
 class HIP(dns.rdata.Rdata):
+
     """HIP record
 
     @ivar hit: the host identity tag
@@ -44,22 +48,23 @@ class HIP(dns.rdata.Rdata):
         self.servers = servers
 
     def to_text(self, origin=None, relativize=True, **kw):
-        hit = self.hit.encode('hex-codec')
-        key = self.key.encode('base64-codec').replace('\n', '')
-        text = ''
+        hit = binascii.hexlify(self.hit).decode()
+        key = base64.b64encode(self.key).replace(b'\n', b'').decode()
+        text = u''
         servers = []
         for server in self.servers:
-            servers.append(str(server.choose_relativity(origin, relativize)))
+            servers.append(server.choose_relativity(origin, relativize))
         if len(servers) > 0:
-            text += (' ' + ' '.join(servers))
-        return '%u %s %s%s' % (self.algorithm, hit, key, text)
+            text += (u' ' + u' '.join(map(lambda x: x.to_unicode(), servers)))
+        return u'%u %s %s%s' % (self.algorithm, hit, key, text)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         algorithm = tok.get_uint8()
-        hit = tok.get_string().decode('hex-codec')
+        hit = binascii.unhexlify(tok.get_string().encode())
         if len(hit) > 255:
             raise dns.exception.SyntaxError("HIT too long")
-        key = tok.get_string().decode('base64-codec')
+        key = base64.b64decode(tok.get_string().encode())
         servers = []
         while 1:
             token = tok.get()
@@ -70,9 +75,7 @@ class HIP(dns.rdata.Rdata):
             servers.append(server)
         return cls(rdclass, rdtype, hit, algorithm, key, servers)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         lh = len(self.hit)
         lk = len(self.key)
         file.write(struct.pack("!BBH", lh, self.algorithm, lk))
@@ -81,15 +84,16 @@ class HIP(dns.rdata.Rdata):
         for server in self.servers:
             server.to_wire(file, None, origin)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (lh, algorithm, lk) = struct.unpack('!BBH',
-                                            wire[current : current + 4])
+                                            wire[current: current + 4])
         current += 4
         rdlen -= 4
-        hit = wire[current : current + lh].unwrap()
+        hit = wire[current: current + lh].unwrap()
         current += lh
         rdlen -= lh
-        key = wire[current : current + lk].unwrap()
+        key = wire[current: current + lk].unwrap()
         current += lk
         rdlen -= lk
         servers = []
@@ -98,14 +102,12 @@ class HIP(dns.rdata.Rdata):
                                                  current)
             current += cused
             rdlen -= cused
-            if not origin is None:
+            if origin is not None:
                 server = server.relativize(origin)
             servers.append(server)
         return cls(rdclass, rdtype, hit, algorithm, key, servers)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         servers = []
         for server in self.servers:
             server = server.choose_relativity(origin, relativize)
@@ -113,19 +115,19 @@ class HIP(dns.rdata.Rdata):
         self.servers = servers
 
     def _cmp(self, other):
-        b1 = cStringIO.StringIO()
+        b1 = BytesIO()
         lh = len(self.hit)
         lk = len(self.key)
         b1.write(struct.pack("!BBH", lh, self.algorithm, lk))
         b1.write(self.hit)
         b1.write(self.key)
-        b2 = cStringIO.StringIO()
+        b2 = BytesIO()
         lh = len(other.hit)
         lk = len(other.key)
         b2.write(struct.pack("!BBH", lh, other.algorithm, lk))
         b2.write(other.hit)
         b2.write(other.key)
-        v = cmp(b1.getvalue(), b2.getvalue())
+        v = xcmp(b1.getvalue(), b2.getvalue())
         if v != 0:
             return v
         ls = len(self.servers)
@@ -133,7 +135,7 @@ class HIP(dns.rdata.Rdata):
         count = min(ls, lo)
         i = 0
         while i < count:
-            v = cmp(self.servers[i], other.servers[i])
+            v = xcmp(self.servers[i], other.servers[i])
             if v != 0:
                 return v
             i += 1
Index: dnspython-1.12.0/dns/rdtypes/ANY/ISDN.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/ISDN.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/ISDN.py
@@ -13,11 +13,17 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import text_type
+from dns._compat import xcmp
+
 
 class ISDN(dns.rdata.Rdata):
+
     """ISDN record
 
     @ivar address: the ISDN address
@@ -30,8 +36,14 @@ class ISDN(dns.rdata.Rdata):
 
     def __init__(self, rdclass, rdtype, address, subaddress):
         super(ISDN, self).__init__(rdclass, rdtype)
-        self.address = address
-        self.subaddress = subaddress
+        if isinstance(address, text_type):
+            self.address = address.encode()
+        else:
+            self.address = address
+        if isinstance(address, text_type):
+            self.subaddress = subaddress.encode()
+        else:
+            self.subaddress = subaddress
 
     def to_text(self, origin=None, relativize=True, **kw):
         if self.subaddress:
@@ -40,7 +52,8 @@ class ISDN(dns.rdata.Rdata):
         else:
             return '"%s"' % dns.rdata._escapify(self.address)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         address = tok.get_string()
         t = tok.get()
         if not t.is_eol_or_eof():
@@ -52,23 +65,20 @@ class ISDN(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, address, subaddress)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         l = len(self.address)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.address)
         l = len(self.subaddress)
         if l > 0:
             assert l < 256
-            byte = chr(l)
-            file.write(byte)
+            file.write(struct.pack('!B', l))
             file.write(self.subaddress)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
@@ -77,7 +87,7 @@ class ISDN(dns.rdata.Rdata):
         current += l
         rdlen -= l
         if rdlen > 0:
-            l = ord(wire[current])
+            l = wire[current]
             current += 1
             rdlen -= 1
             if l != rdlen:
@@ -87,10 +97,8 @@ class ISDN(dns.rdata.Rdata):
             subaddress = ''
         return cls(rdclass, rdtype, address, subaddress)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        v = cmp(self.address, other.address)
+        v = xcmp(self.address, other.address)
         if v == 0:
-            v = cmp(self.subaddress, other.subaddress)
+            v = xcmp(self.subaddress, other.subaddress)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/LOC.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/LOC.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/LOC.py
@@ -13,32 +13,36 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
 import struct
 
 import dns.exception
 import dns.rdata
+from dns._compat import long, xrange
+from io import BytesIO
+from dns._compat import xcmp
 
-_pows = (1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L,
-         100000000L, 1000000000L, 10000000000L)
+
+_pows = tuple(long(10**i) for i in range(0, 11))
 
 # default values are in centimeters
 _default_size = 100.0
 _default_hprec = 1000000.0
 _default_vprec = 1000.0
 
+
 def _exponent_of(what, desc):
     if what == 0:
         return 0
     exp = None
     for i in xrange(len(_pows)):
-        if what // _pows[i] == 0L:
+        if what // _pows[i] == long(0):
             exp = i - 1
             break
     if exp is None or exp < 0:
         raise dns.exception.SyntaxError("%s value out of bounds" % desc)
     return exp
 
+
 def _float_to_tuple(what):
     if what < 0:
         sign = -1
@@ -55,6 +59,7 @@ def _float_to_tuple(what):
     what = int(what)
     return (degrees * sign, minutes, seconds, what)
 
+
 def _tuple_to_float(what):
     if what[0] < 0:
         sign = -1
@@ -67,12 +72,14 @@ def _tuple_to_float(what):
     value += float(what[3]) / 3600000.0
     return sign * value
 
+
 def _encode_size(what, desc):
-    what = long(what);
+    what = long(what)
     exponent = _exponent_of(what, desc) & 0xF
     base = what // pow(10, exponent) & 0xF
     return base * 16 + exponent
 
+
 def _decode_size(what, desc):
     exponent = what & 0x0F
     if exponent > 9:
@@ -82,7 +89,9 @@ def _decode_size(what, desc):
         raise dns.exception.SyntaxError("bad %s base" % desc)
     return long(base) * pow(10, exponent)
 
+
 class LOC(dns.rdata.Rdata):
+
     """LOC record
 
     @ivar latitude: latitude
@@ -105,7 +114,8 @@ class LOC(dns.rdata.Rdata):
                  'horizontal_precision', 'vertical_precision']
 
     def __init__(self, rdclass, rdtype, latitude, longitude, altitude,
-                 size=_default_size, hprec=_default_hprec, vprec=_default_vprec):
+                 size=_default_size, hprec=_default_hprec,
+                 vprec=_default_vprec):
         """Initialize a LOC record instance.
 
         The parameters I{latitude} and I{longitude} may be either a 4-tuple
@@ -147,19 +157,20 @@ class LOC(dns.rdata.Rdata):
             lat_degrees, self.latitude[1], self.latitude[2], self.latitude[3],
             lat_hemisphere, long_degrees, self.longitude[1], self.longitude[2],
             self.longitude[3], long_hemisphere, self.altitude / 100.0
-            )
+        )
 
         # do not print default values
         if self.size != _default_size or \
             self.horizontal_precision != _default_hprec or \
-            self.vertical_precision != _default_vprec:
+                self.vertical_precision != _default_vprec:
             text += " %0.2fm %0.2fm %0.2fm" % (
                 self.size / 100.0, self.horizontal_precision / 100.0,
                 self.vertical_precision / 100.0
             )
         return text
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         latitude = [0, 0, 0, 0]
         longitude = [0, 0, 0, 0]
         size = _default_size
@@ -174,13 +185,15 @@ class LOC(dns.rdata.Rdata):
             if '.' in t:
                 (seconds, milliseconds) = t.split('.')
                 if not seconds.isdigit():
-                    raise dns.exception.SyntaxError('bad latitude seconds value')
+                    raise dns.exception.SyntaxError(
+                        'bad latitude seconds value')
                 latitude[2] = int(seconds)
                 if latitude[2] >= 60:
                     raise dns.exception.SyntaxError('latitude seconds >= 60')
                 l = len(milliseconds)
                 if l == 0 or l > 3 or not milliseconds.isdigit():
-                    raise dns.exception.SyntaxError('bad latitude milliseconds value')
+                    raise dns.exception.SyntaxError(
+                        'bad latitude milliseconds value')
                 if l == 1:
                     m = 100
                 elif l == 2:
@@ -205,13 +218,15 @@ class LOC(dns.rdata.Rdata):
             if '.' in t:
                 (seconds, milliseconds) = t.split('.')
                 if not seconds.isdigit():
-                    raise dns.exception.SyntaxError('bad longitude seconds value')
+                    raise dns.exception.SyntaxError(
+                        'bad longitude seconds value')
                 longitude[2] = int(seconds)
                 if longitude[2] >= 60:
                     raise dns.exception.SyntaxError('longitude seconds >= 60')
                 l = len(milliseconds)
                 if l == 0 or l > 3 or not milliseconds.isdigit():
-                    raise dns.exception.SyntaxError('bad longitude milliseconds value')
+                    raise dns.exception.SyntaxError(
+                        'bad longitude milliseconds value')
                 if l == 1:
                     m = 100
                 elif l == 2:
@@ -256,7 +271,6 @@ class LOC(dns.rdata.Rdata):
         return cls(rdclass, rdtype, latitude, longitude, altitude,
                    size, hprec, vprec)
 
-    from_text = classmethod(from_text)
 
     def to_wire(self, file, compress = None, origin = None):
         if self.latitude[0] < 0:
@@ -269,7 +283,7 @@ class LOC(dns.rdata.Rdata):
                         self.latitude[1] * 60000 +
                         self.latitude[2] * 1000 +
                         self.latitude[3]) * sign
-        latitude = 0x80000000L + milliseconds
+        latitude = long(0x80000000) + milliseconds
         if self.longitude[0] < 0:
             sign = -1
             degrees = long(-1 * self.longitude[0])
@@ -280,8 +294,8 @@ class LOC(dns.rdata.Rdata):
                         self.longitude[1] * 60000 +
                         self.longitude[2] * 1000 +
                         self.longitude[3]) * sign
-        longitude = 0x80000000L + milliseconds
-        altitude = long(self.altitude) + 10000000L
+        longitude = long(0x80000000) + milliseconds
+        altitude = long(self.altitude) + long(10000000)
         size = _encode_size(self.size, "size")
         hprec = _encode_size(self.horizontal_precision, "horizontal precision")
         vprec = _encode_size(self.vertical_precision, "vertical precision")
@@ -289,19 +303,20 @@ class LOC(dns.rdata.Rdata):
                            longitude, altitude)
         file.write(wire)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (version, size, hprec, vprec, latitude, longitude, altitude) = \
-                  struct.unpack("!BBBBIII", wire[current : current + rdlen])
-        if latitude > 0x80000000L:
-            latitude = float(latitude - 0x80000000L) / 3600000
+            struct.unpack("!BBBBIII", wire[current: current + rdlen])
+        if latitude > long(0x80000000):
+            latitude = float(latitude - long(0x80000000)) / 3600000
         else:
-            latitude = -1 * float(0x80000000L - latitude) / 3600000
+            latitude = -1 * float(long(0x80000000) - latitude) / 3600000
         if latitude < -90.0 or latitude > 90.0:
             raise dns.exception.FormError("bad latitude")
-        if longitude > 0x80000000L:
-            longitude = float(longitude - 0x80000000L) / 3600000
+        if longitude > long(0x80000000):
+            longitude = float(longitude - long(0x80000000)) / 3600000
         else:
-            longitude = -1 * float(0x80000000L - longitude) / 3600000
+            longitude = -1 * float(long(0x80000000) - longitude) / 3600000
         if longitude < -180.0 or longitude > 180.0:
             raise dns.exception.FormError("bad longitude")
         altitude = float(altitude) - 10000000.0
@@ -311,10 +326,8 @@ class LOC(dns.rdata.Rdata):
         return cls(rdclass, rdtype, latitude, longitude, altitude,
                    size, hprec, vprec)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f)
         wire1 = f.getvalue()
         f.seek(0)
@@ -323,7 +336,7 @@ class LOC(dns.rdata.Rdata):
         wire2 = f.getvalue()
         f.close()
 
-        return cmp(wire1, wire2)
+        return xcmp(wire1, wire2)
 
     def _get_float_latitude(self):
         return _tuple_to_float(self.latitude)
Index: dnspython-1.12.0/dns/rdtypes/ANY/MX.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/MX.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/MX.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.mxbase
 
+
 class MX(dns.rdtypes.mxbase.MXBase):
+
     """MX record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/NS.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/NS.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/NS.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.nsbase
 
+
 class NS(dns.rdtypes.nsbase.NSBase):
+
     """NS record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/NSEC.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/NSEC.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/NSEC.py
@@ -13,14 +13,17 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+import struct
 
 import dns.exception
 import dns.rdata
 import dns.rdatatype
 import dns.name
+from dns._compat import xrange
+
 
 class NSEC(dns.rdata.Rdata):
+
     """NSEC record
 
     @ivar next: the next name
@@ -41,15 +44,16 @@ class NSEC(dns.rdata.Rdata):
         for (window, bitmap) in self.windows:
             bits = []
             for i in xrange(0, len(bitmap)):
-                byte = ord(bitmap[i])
+                byte = bitmap[i]
                 for j in xrange(0, 8):
                     if byte & (0x80 >> j):
-                        bits.append(dns.rdatatype.to_text(window * 256 + \
+                        bits.append(dns.rdatatype.to_text(window * 256 +
                                                           i * 8 + j))
             text += (' ' + ' '.join(bits))
         return '%s%s' % (next, text)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         next = tok.get_name()
         next = next.choose_relativity(origin, relativize)
         rdtypes = []
@@ -67,7 +71,7 @@ class NSEC(dns.rdata.Rdata):
         window = 0
         octets = 0
         prior_rdtype = 0
-        bitmap = ['\0'] * 32
+        bitmap = bytearray(b'\0' * 32)
         windows = []
         for nrdtype in rdtypes:
             if nrdtype == prior_rdtype:
@@ -75,27 +79,26 @@ class NSEC(dns.rdata.Rdata):
             prior_rdtype = nrdtype
             new_window = nrdtype // 256
             if new_window != window:
-                windows.append((window, ''.join(bitmap[0:octets])))
-                bitmap = ['\0'] * 32
+                windows.append((window, bitmap[0:octets]))
+                bitmap = bytearray(b'\0' * 32)
                 window = new_window
             offset = nrdtype % 256
             byte = offset // 8
             bit = offset % 8
             octets = byte + 1
-            bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
-        windows.append((window, ''.join(bitmap[0:octets])))
-        return cls(rdclass, rdtype, next, windows)
+            bitmap[byte] = bitmap[byte] | (0x80 >> bit)
 
-    from_text = classmethod(from_text)
+        windows.append((window, bitmap[0:octets]))
+        return cls(rdclass, rdtype, next, windows)
 
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         self.next.to_wire(file, None, origin)
         for (window, bitmap) in self.windows:
-            file.write(chr(window))
-            file.write(chr(len(bitmap)))
+            file.write(struct.pack('!BB', window, len(bitmap)))
             file.write(bitmap)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
         current += cused
         rdlen -= cused
@@ -103,25 +106,23 @@ class NSEC(dns.rdata.Rdata):
         while rdlen > 0:
             if rdlen < 3:
                 raise dns.exception.FormError("NSEC too short")
-            window = ord(wire[current])
-            octets = ord(wire[current + 1])
+            window = wire[current]
+            octets = wire[current + 1]
             if octets == 0 or octets > 32:
                 raise dns.exception.FormError("bad NSEC octets")
             current += 2
             rdlen -= 2
             if rdlen < octets:
                 raise dns.exception.FormError("bad NSEC bitmap length")
-            bitmap = wire[current : current + octets].unwrap()
+            bitmap = bytearray(wire[current: current + octets].unwrap())
             current += octets
             rdlen -= octets
             windows.append((window, bitmap))
-        if not origin is None:
+        if origin is not None:
             next = next.relativize(origin)
         return cls(rdclass, rdtype, next, windows)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.next = self.next.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
Index: dnspython-1.12.0/dns/rdtypes/ANY/NSEC3.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/NSEC3.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/NSEC3.py
@@ -13,19 +13,28 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+from io import BytesIO
 import base64
-import cStringIO
+import binascii
 import string
 import struct
 
 import dns.exception
 import dns.rdata
 import dns.rdatatype
+from dns._compat import xrange, text_type
+from dns._compat import xcmp
 
-b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
-                                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
-b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
-                                     '0123456789ABCDEFGHIJKLMNOPQRSTUV')
+try:
+    b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
+                                         'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
+    b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
+                                         '0123456789ABCDEFGHIJKLMNOPQRSTUV')
+except AttributeError:
+    b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV',
+                                        b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
+    b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
+                                        b'0123456789ABCDEFGHIJKLMNOPQRSTUV')
 
 # hash algorithm constants
 SHA1 = 1
@@ -33,7 +42,9 @@ SHA1 = 1
 # flag constants
 OPTOUT = 1
 
+
 class NSEC3(dns.rdata.Rdata):
+
     """NSEC3 record
 
     @ivar algorithm: the hash algorithm number
@@ -57,39 +68,45 @@ class NSEC3(dns.rdata.Rdata):
         self.algorithm = algorithm
         self.flags = flags
         self.iterations = iterations
-        self.salt = salt
+        if isinstance(salt, text_type):
+            self.salt = salt.encode()
+        else:
+            self.salt = salt
         self.next = next
         self.windows = windows
 
     def to_text(self, origin=None, relativize=True, **kw):
-        next = base64.b32encode(self.next).translate(b32_normal_to_hex).lower()
-        if self.salt == '':
+        next = base64.b32encode(self.next).translate(
+            b32_normal_to_hex).lower().decode()
+        if self.salt == b'':
             salt = '-'
         else:
-            salt = self.salt.encode('hex-codec')
-        text = ''
+            salt = binascii.hexlify(self.salt).decode()
+        text = u''
         for (window, bitmap) in self.windows:
             bits = []
             for i in xrange(0, len(bitmap)):
-                byte = ord(bitmap[i])
+                byte = bitmap[i]
                 for j in xrange(0, 8):
                     if byte & (0x80 >> j):
-                        bits.append(dns.rdatatype.to_text(window * 256 + \
+                        bits.append(dns.rdatatype.to_text(window * 256 +
                                                           i * 8 + j))
-            text += (' ' + ' '.join(bits))
-        return '%u %u %u %s %s%s' % (self.algorithm, self.flags, self.iterations,
-                                     salt, next, text)
+            text += (u' ' + u' '.join(bits))
+        return u'%u %u %u %s %s%s' % (self.algorithm, self.flags,
+                                      self.iterations, salt, next, text)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         algorithm = tok.get_uint8()
         flags = tok.get_uint8()
         iterations = tok.get_uint16()
         salt = tok.get_string()
-        if salt == '-':
-            salt = ''
+        if salt == u'-':
+            salt = b''
         else:
-            salt = salt.decode('hex-codec')
-        next = tok.get_string().upper().translate(b32_hex_to_normal)
+            salt = binascii.unhexlify(salt.encode('ascii'))
+        next = tok.get_string().encode(
+            'ascii').upper().translate(b32_hex_to_normal)
         next = base64.b32decode(next)
         rdtypes = []
         while 1:
@@ -106,7 +123,7 @@ class NSEC3(dns.rdata.Rdata):
         window = 0
         octets = 0
         prior_rdtype = 0
-        bitmap = ['\0'] * 32
+        bitmap = bytearray(b'\0' * 32)
         windows = []
         for nrdtype in rdtypes:
             if nrdtype == prior_rdtype:
@@ -116,20 +133,19 @@ class NSEC3(dns.rdata.Rdata):
             if new_window != window:
                 if octets != 0:
                     windows.append((window, ''.join(bitmap[0:octets])))
-                bitmap = ['\0'] * 32
+                bitmap = bytearray(b'\0' * 32)
                 window = new_window
             offset = nrdtype % 256
             byte = offset // 8
             bit = offset % 8
             octets = byte + 1
-            bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
+            bitmap[byte] = bitmap[byte] | (0x80 >> bit)
         if octets != 0:
-            windows.append((window, ''.join(bitmap[0:octets])))
-        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
-
-    from_text = classmethod(from_text)
+            windows.append((window, bitmap[0:octets]))
+        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
+                   windows)
 
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         l = len(self.salt)
         file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                                self.iterations, l))
@@ -138,19 +154,19 @@ class NSEC3(dns.rdata.Rdata):
         file.write(struct.pack("!B", l))
         file.write(self.next)
         for (window, bitmap) in self.windows:
-            file.write(chr(window))
-            file.write(chr(len(bitmap)))
+            file.write(struct.pack("!BB", window, len(bitmap)))
             file.write(bitmap)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
-                                                             wire[current : current + 5])
+        (algorithm, flags, iterations, slen) = \
+            struct.unpack('!BBHB', wire[current: current + 5])
         current += 5
         rdlen -= 5
         salt = wire[current : current + slen].unwrap()
         current += slen
         rdlen -= slen
-        (nlen, ) = struct.unpack('!B', wire[current])
+        nlen = wire[current]
         current += 1
         rdlen -= 1
         next = wire[current : current + nlen].unwrap()
@@ -160,25 +176,23 @@ class NSEC3(dns.rdata.Rdata):
         while rdlen > 0:
             if rdlen < 3:
                 raise dns.exception.FormError("NSEC3 too short")
-            window = ord(wire[current])
-            octets = ord(wire[current + 1])
+            window = wire[current]
+            octets = wire[current + 1]
             if octets == 0 or octets > 32:
                 raise dns.exception.FormError("bad NSEC3 octets")
             current += 2
             rdlen -= 2
             if rdlen < octets:
                 raise dns.exception.FormError("bad NSEC3 bitmap length")
-            bitmap = wire[current : current + octets].unwrap()
+            bitmap = bytearray(wire[current: current + octets].unwrap())
             current += octets
             rdlen -= octets
             windows.append((window, bitmap))
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        b1 = cStringIO.StringIO()
+        b1 = BytesIO()
         self.to_wire(b1)
-        b2 = cStringIO.StringIO()
+        b2 = BytesIO()
         other.to_wire(b2)
-        return cmp(b1.getvalue(), b2.getvalue())
+        return xcmp(b1.getvalue(), b2.getvalue())
Index: dnspython-1.12.0/dns/rdtypes/ANY/NSEC3PARAM.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/NSEC3PARAM.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/NSEC3PARAM.py
@@ -13,13 +13,18 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+from io import BytesIO
 import struct
+import binascii
 
 import dns.exception
 import dns.rdata
+from dns._compat import text_type
+from dns._compat import xcmp
+
 
 class NSEC3PARAM(dns.rdata.Rdata):
+
     """NSEC3PARAM record
 
     @ivar algorithm: the hash algorithm number
@@ -38,16 +43,21 @@ class NSEC3PARAM(dns.rdata.Rdata):
         self.algorithm = algorithm
         self.flags = flags
         self.iterations = iterations
-        self.salt = salt
+        if isinstance(salt, text_type):
+            self.salt = salt.encode()
+        else:
+            self.salt = salt
 
     def to_text(self, origin=None, relativize=True, **kw):
-        if self.salt == '':
+        if self.salt == b'':
             salt = '-'
         else:
-            salt = self.salt.encode('hex-codec')
-        return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations, salt)
+            salt = binascii.hexlify(self.salt).decode()
+        return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations,
+                                salt)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         algorithm = tok.get_uint8()
         flags = tok.get_uint8()
         iterations = tok.get_uint16()
@@ -55,21 +65,21 @@ class NSEC3PARAM(dns.rdata.Rdata):
         if salt == '-':
             salt = ''
         else:
-            salt = salt.decode('hex-codec')
+            salt = binascii.unhexlify(salt.encode())
         tok.get_eol()
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         l = len(self.salt)
         file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                                self.iterations, l))
         file.write(self.salt)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
-                                                             wire[current : current + 5])
+        (algorithm, flags, iterations, slen) = \
+             struct.unpack('!BBHB',
+                           wire[current: current + 5])
         current += 5
         rdlen -= 5
         salt = wire[current : current + slen].unwrap()
@@ -79,11 +89,9 @@ class NSEC3PARAM(dns.rdata.Rdata):
             raise dns.exception.FormError
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        b1 = cStringIO.StringIO()
+        b1 = BytesIO()
         self.to_wire(b1)
-        b2 = cStringIO.StringIO()
+        b2 = BytesIO()
         other.to_wire(b2)
-        return cmp(b1.getvalue(), b2.getvalue())
+        return xcmp(b1.getvalue(), b2.getvalue())
Index: dnspython-1.12.0/dns/rdtypes/ANY/PTR.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/PTR.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/PTR.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.nsbase
 
+
 class PTR(dns.rdtypes.nsbase.NSBase):
+
     """PTR record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/RP.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/RP.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/RP.py
@@ -16,8 +16,11 @@
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class RP(dns.rdata.Rdata):
+
     """RP record
 
     @ivar mbox: The responsible person's mailbox
@@ -39,7 +42,8 @@ class RP(dns.rdata.Rdata):
         txt = self.txt.choose_relativity(origin, relativize)
         return "%s %s" % (str(mbox), str(txt))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         mbox = tok.get_name()
         txt = tok.get_name()
         mbox = mbox.choose_relativity(origin, relativize)
@@ -47,17 +51,16 @@ class RP(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, mbox, txt)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         self.mbox.to_wire(file, None, origin)
         self.txt.to_wire(file, None, origin)
 
-    def to_digestable(self, origin = None):
+    def to_digestable(self, origin=None):
         return self.mbox.to_digestable(origin) + \
             self.txt.to_digestable(origin)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (mbox, cused) = dns.name.from_wire(wire[: current + rdlen],
                                            current)
         current += cused
@@ -68,19 +71,17 @@ class RP(dns.rdata.Rdata):
                                           current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             mbox = mbox.relativize(origin)
             txt = txt.relativize(origin)
         return cls(rdclass, rdtype, mbox, txt)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.mbox = self.mbox.choose_relativity(origin, relativize)
         self.txt = self.txt.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
-        v = cmp(self.mbox, other.mbox)
+        v = xcmp(self.mbox, other.mbox)
         if v == 0:
-            v = cmp(self.txt, other.txt)
+            v = xcmp(self.txt, other.txt)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/RRSIG.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/RRSIG.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/RRSIG.py
@@ -13,6 +13,7 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import base64
 import calendar
 import struct
 import time
@@ -38,10 +39,13 @@ def sigtime_to_posixtime(what):
     return calendar.timegm((year, month, day, hour, minute, second,
                             0, 0, 0))
 
+
 def posixtime_to_sigtime(what):
     return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))
 
+
 class RRSIG(dns.rdata.Rdata):
+
     """RRSIG record
 
     @ivar type_covered: the rdata type this signature covers
@@ -95,9 +99,10 @@ class RRSIG(dns.rdata.Rdata):
             self.key_tag,
             self.signer.choose_relativity(origin, relativize),
             dns.rdata._base64ify(self.signature)
-            )
+        )
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         type_covered = dns.rdatatype.from_text(tok.get_string())
         algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
         labels = tok.get_int()
@@ -114,16 +119,14 @@ class RRSIG(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        b64 = ''.join(chunks)
-        signature = b64.decode('base64_codec')
+            chunks.append(t.value.encode())
+        b64 = b''.join(chunks)
+        signature = base64.b64decode(b64)
         return cls(rdclass, rdtype, type_covered, algorithm, labels,
                    original_ttl, expiration, inception, key_tag, signer,
                    signature)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         header = struct.pack('!HBBIIIH', self.type_covered,
                              self.algorithm, self.labels,
                              self.original_ttl, self.expiration,
@@ -132,23 +135,22 @@ class RRSIG(dns.rdata.Rdata):
         self.signer.to_wire(file, None, origin)
         file.write(self.signature)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        header = struct.unpack('!HBBIIIH', wire[current : current + 18])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        header = struct.unpack('!HBBIIIH', wire[current: current + 18])
         current += 18
         rdlen -= 18
         (signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
         current += cused
         rdlen -= cused
-        if not origin is None:
+        if origin is not None:
             signer = signer.relativize(origin)
-        signature = wire[current : current + rdlen].unwrap()
+        signature = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2],
                    header[3], header[4], header[5], header[6], signer,
                    signature)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.signer = self.signer.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
Index: dnspython-1.12.0/dns/rdtypes/ANY/RT.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/RT.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/RT.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.mxbase
 
+
 class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX):
+
     """RT record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/SOA.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/SOA.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/SOA.py
@@ -18,8 +18,11 @@ import struct
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class SOA(dns.rdata.Rdata):
+
     """SOA record
 
     @ivar mname: the SOA MNAME (master name) field
@@ -58,9 +61,10 @@ class SOA(dns.rdata.Rdata):
         rname = self.rname.choose_relativity(origin, relativize)
         return '%s %s %d %d %d %d %d' % (
             mname, rname, self.serial, self.refresh, self.retry,
-            self.expire, self.minimum )
+            self.expire, self.minimum)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         mname = tok.get_name()
         rname = tok.get_name()
         mname = mname.choose_relativity(origin, relativize)
@@ -72,24 +76,23 @@ class SOA(dns.rdata.Rdata):
         minimum = tok.get_ttl()
         tok.get_eol()
         return cls(rdclass, rdtype, mname, rname, serial, refresh, retry,
-                   expire, minimum )
+                   expire, minimum)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         self.mname.to_wire(file, compress, origin)
         self.rname.to_wire(file, compress, origin)
         five_ints = struct.pack('!IIIII', self.serial, self.refresh,
                                 self.retry, self.expire, self.minimum)
         file.write(five_ints)
 
-    def to_digestable(self, origin = None):
+    def to_digestable(self, origin=None):
         return self.mname.to_digestable(origin) + \
             self.rname.to_digestable(origin) + \
             struct.pack('!IIIII', self.serial, self.refresh,
                         self.retry, self.expire, self.minimum)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (mname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
         current += cused
         rdlen -= cused
@@ -99,29 +102,27 @@ class SOA(dns.rdata.Rdata):
         if rdlen != 20:
             raise dns.exception.FormError
         five_ints = struct.unpack('!IIIII',
-                                  wire[current : current + rdlen])
-        if not origin is None:
+                                  wire[current: current + rdlen])
+        if origin is not None:
             mname = mname.relativize(origin)
             rname = rname.relativize(origin)
         return cls(rdclass, rdtype, mname, rname,
                    five_ints[0], five_ints[1], five_ints[2], five_ints[3],
                    five_ints[4])
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.mname = self.mname.choose_relativity(origin, relativize)
         self.rname = self.rname.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
-        v = cmp(self.mname, other.mname)
+        v = xcmp(self.mname, other.mname)
         if v == 0:
-            v = cmp(self.rname, other.rname)
+            v = xcmp(self.rname, other.rname)
             if v == 0:
                 self_ints = struct.pack('!IIIII', self.serial, self.refresh,
                                         self.retry, self.expire, self.minimum)
                 other_ints = struct.pack('!IIIII', other.serial, other.refresh,
                                          other.retry, other.expire,
                                          other.minimum)
-                v = cmp(self_ints, other_ints)
+                v = xcmp(self_ints, other_ints)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/SPF.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/SPF.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/SPF.py
@@ -15,7 +15,9 @@
 
 import dns.rdtypes.txtbase
 
+
 class SPF(dns.rdtypes.txtbase.TXTBase):
+
     """SPF record
 
     @see: RFC 4408"""
Index: dnspython-1.12.0/dns/rdtypes/ANY/SSHFP.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/SSHFP.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/SSHFP.py
@@ -14,11 +14,15 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
+from dns._compat import xcmp
+
 
 class SSHFP(dns.rdata.Rdata):
+
     """SSHFP record
 
     @ivar algorithm: the algorithm
@@ -44,7 +48,8 @@ class SSHFP(dns.rdata.Rdata):
                              dns.rdata._hexify(self.fingerprint,
                                                chunksize=128))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         algorithm = tok.get_uint8()
         fp_type = tok.get_uint8()
         chunks = []
@@ -54,18 +59,17 @@ class SSHFP(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        fingerprint = ''.join(chunks)
-        fingerprint = fingerprint.decode('hex_codec')
+            chunks.append(t.value.encode())
+        fingerprint = b''.join(chunks)
+        fingerprint = binascii.unhexlify(fingerprint)
         return cls(rdclass, rdtype, algorithm, fp_type, fingerprint)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         header = struct.pack("!BB", self.algorithm, self.fp_type)
         file.write(header)
         file.write(self.fingerprint)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         header = struct.unpack("!BB", wire[current : current + 2])
         current += 2
@@ -73,12 +77,10 @@ class SSHFP(dns.rdata.Rdata):
         fingerprint = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], fingerprint)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         hs = struct.pack("!BB", self.algorithm, self.fp_type)
         ho = struct.pack("!BB", other.algorithm, other.fp_type)
-        v = cmp(hs, ho)
+        v = xcmp(hs, ho)
         if v == 0:
-            v = cmp(self.fingerprint, other.fingerprint)
+            v = xcmp(self.fingerprint, other.fingerprint)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/TLSA.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/TLSA.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/TLSA.py
@@ -14,11 +14,15 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
+from dns._compat import xcmp
+
 
 class TLSA(dns.rdata.Rdata):
+
     """TLSA record
 
     @ivar usage: The certificate usage
@@ -46,9 +50,10 @@ class TLSA(dns.rdata.Rdata):
                                 self.selector,
                                 self.mtype,
                                 dns.rdata._hexify(self.cert,
-                                               chunksize=128))
+                                                  chunksize=128))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         usage = tok.get_uint8()
         selector = tok.get_uint8()
         mtype = tok.get_uint8()
@@ -59,18 +64,17 @@ class TLSA(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            cert_chunks.append(t.value)
-        cert = ''.join(cert_chunks)
-        cert = cert.decode('hex_codec')
+            cert_chunks.append(t.value.encode())
+        cert = b''.join(cert_chunks)
+        cert = binascii.unhexlify(cert)
         return cls(rdclass, rdtype, usage, selector, mtype, cert)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         header = struct.pack("!BBB", self.usage, self.selector, self.mtype)
         file.write(header)
         file.write(self.cert)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         header = struct.unpack("!BBB", wire[current : current + 3])
         current += 3
@@ -78,12 +82,10 @@ class TLSA(dns.rdata.Rdata):
         cert = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2], cert)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         hs = struct.pack("!BBB", self.usage, self.selector, self.mtype)
         ho = struct.pack("!BBB", other.usage, other.selector, other.mtype)
-        v = cmp(hs, ho)
+        v = xcmp(hs, ho)
         if v == 0:
-            v = cmp(self.cert, other.cert)
+            v = xcmp(self.cert, other.cert)
         return v
Index: dnspython-1.12.0/dns/rdtypes/ANY/TXT.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/TXT.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/TXT.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.txtbase
 
+
 class TXT(dns.rdtypes.txtbase.TXTBase):
+
     """TXT record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/ANY/X25.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/ANY/X25.py
+++ dnspython-1.12.0/dns/rdtypes/ANY/X25.py
@@ -13,11 +13,17 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import text_type
+from dns._compat import xcmp
+
 
 class X25(dns.rdata.Rdata):
+
     """X25 record
 
     @ivar address: the PSDN address
@@ -28,27 +34,28 @@ class X25(dns.rdata.Rdata):
 
     def __init__(self, rdclass, rdtype, address):
         super(X25, self).__init__(rdclass, rdtype)
-        self.address = address
+        if isinstance(address, text_type):
+            self.address = address.encode()
+        else:
+            self.address = address
 
     def to_text(self, origin=None, relativize=True, **kw):
         return '"%s"' % dns.rdata._escapify(self.address)
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         address = tok.get_string()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         l = len(self.address)
         assert l < 256
-        byte = chr(l)
-        file.write(byte)
+        file.write(struct.pack('!B', l))
         file.write(self.address)
 
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
@@ -59,4 +66,4 @@ class X25(dns.rdata.Rdata):
     from_wire = classmethod(from_wire)
 
     def _cmp(self, other):
-        return cmp(self.address, other.address)
+        return xcmp(self.address, other.address)
Index: dnspython-1.12.0/dns/rdtypes/IN/A.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/A.py
+++ dnspython-1.12.0/dns/rdtypes/IN/A.py
@@ -17,8 +17,11 @@ import dns.exception
 import dns.ipv4
 import dns.rdata
 import dns.tokenizer
+from dns._compat import xcmp
+
 
 class A(dns.rdata.Rdata):
+
     """A record.
 
     @ivar address: an IPv4 address
@@ -29,29 +32,27 @@ class A(dns.rdata.Rdata):
     def __init__(self, rdclass, rdtype, address):
         super(A, self).__init__(rdclass, rdtype)
         # check that it's OK
-        junk = dns.ipv4.inet_aton(address)
+        dns.ipv4.inet_aton(address)
         self.address = address
 
     def to_text(self, origin=None, relativize=True, **kw):
         return self.address
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         address = tok.get_identifier()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(dns.ipv4.inet_aton(self.address))
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        address = dns.ipv4.inet_ntoa(wire[current : current + rdlen])
+        address = dns.ipv4.inet_ntoa(wire[current : current + rdlen]).decode()
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         sa = dns.ipv4.inet_aton(self.address)
         oa = dns.ipv4.inet_aton(other.address)
-        return cmp(sa, oa)
+        return xcmp(sa, oa)
Index: dnspython-1.12.0/dns/rdtypes/IN/AAAA.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/AAAA.py
+++ dnspython-1.12.0/dns/rdtypes/IN/AAAA.py
@@ -18,7 +18,11 @@ import dns.inet
 import dns.rdata
 import dns.tokenizer
 
+from dns._compat import xcmp
+
+
 class AAAA(dns.rdata.Rdata):
+
     """AAAA record.
 
     @ivar address: an IPv6 address
@@ -35,24 +39,22 @@ class AAAA(dns.rdata.Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return self.address
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         address = tok.get_identifier()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.address))
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         address = dns.inet.inet_ntop(dns.inet.AF_INET6,
                                      wire[current : current + rdlen])
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         sa = dns.inet.inet_pton(dns.inet.AF_INET6, self.address)
         oa = dns.inet.inet_pton(dns.inet.AF_INET6, other.address)
-        return cmp(sa, oa)
+        return xcmp(sa, oa)
Index: dnspython-1.12.0/dns/rdtypes/IN/APL.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/APL.py
+++ dnspython-1.12.0/dns/rdtypes/IN/APL.py
@@ -13,15 +13,20 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+from io import BytesIO
 import struct
+import binascii
 
 import dns.exception
 import dns.inet
 import dns.rdata
 import dns.tokenizer
+from dns._compat import xrange
+from dns._compat import xcmp
+
 
 class APLItem(object):
+
     """An APL list item.
 
     @ivar family: the address family (IANA address family registry)
@@ -54,7 +59,7 @@ class APLItem(object):
         elif self.family == 2:
             address = dns.inet.inet_pton(dns.inet.AF_INET6, self.address)
         else:
-            address = self.address.decode('hex_codec')
+            address = binascii.unhexlify(self.address)
         #
         # Truncate least significant zero bytes.
         #
@@ -63,7 +68,7 @@ class APLItem(object):
             if address[i] != chr(0):
                 last = i + 1
                 break
-        address = address[0 : last]
+        address = address[0: last]
         l = len(address)
         assert l < 128
         if self.negation:
@@ -72,7 +77,9 @@ class APLItem(object):
         file.write(header)
         file.write(address)
 
+
 class APL(dns.rdata.Rdata):
+
     """APL record.
 
     @ivar items: a list of APL items
@@ -88,7 +95,8 @@ class APL(dns.rdata.Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return ' '.join(map(lambda x: str(x), self.items))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         items = []
         while 1:
             token = tok.get().unescape()
@@ -109,20 +117,19 @@ class APL(dns.rdata.Rdata):
 
         return cls(rdclass, rdtype, items)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         for item in self.items:
             item.to_wire(file)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         items = []
         while 1:
             if rdlen == 0:
                 break
             if rdlen < 4:
                 raise dns.exception.FormError
-            header = struct.unpack('!HBB', wire[current : current + 4])
+            header = struct.unpack('!HBB', wire[current: current + 4])
             afdlen = header[2]
             if afdlen > 127:
                 negation = True
@@ -133,7 +140,7 @@ class APL(dns.rdata.Rdata):
             rdlen -= 4
             if rdlen < afdlen:
                 raise dns.exception.FormError
-            address = wire[current : current + afdlen].unwrap()
+            address = wire[current: current + afdlen].unwrap()
             l = len(address)
             if header[0] == 1:
                 if l < 4:
@@ -155,10 +162,8 @@ class APL(dns.rdata.Rdata):
             items.append(item)
         return cls(rdclass, rdtype, items)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f)
         wire1 = f.getvalue()
         f.seek(0)
@@ -167,4 +172,4 @@ class APL(dns.rdata.Rdata):
         wire2 = f.getvalue()
         f.close()
 
-        return cmp(wire1, wire2)
+        return xcmp(wire1, wire2)
Index: dnspython-1.12.0/dns/rdtypes/IN/DHCID.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/DHCID.py
+++ dnspython-1.12.0/dns/rdtypes/IN/DHCID.py
@@ -13,9 +13,14 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import base64
+
 import dns.exception
+from dns._compat import xcmp
+
 
 class DHCID(dns.rdata.Rdata):
+
     """DHCID record
 
     @ivar data: the data (the content of the RR is opaque as far as the
@@ -32,7 +37,8 @@ class DHCID(dns.rdata.Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return dns.rdata._base64ify(self.data)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         chunks = []
         while 1:
             t = tok.get().unescape()
@@ -40,21 +46,18 @@ class DHCID(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        b64 = ''.join(chunks)
-        data = b64.decode('base64_codec')
+            chunks.append(t.value.encode())
+        b64 = b''.join(chunks)
+        data = base64.b64decode(b64)
         return cls(rdclass, rdtype, data)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(self.data)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         data = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, data)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        return cmp(self.data, other.data)
+        return xcmp(self.data, other.data)
Index: dnspython-1.12.0/dns/rdtypes/IN/IPSECKEY.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/IPSECKEY.py
+++ dnspython-1.12.0/dns/rdtypes/IN/IPSECKEY.py
@@ -13,14 +13,18 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+from io import BytesIO
 import struct
+import base64
 
 import dns.exception
 import dns.inet
 import dns.name
+from dns._compat import xcmp
+
 
 class IPSECKEY(dns.rdata.Rdata):
+
     """IPSECKEY record
 
     @ivar precedence: the precedence for this key data
@@ -41,19 +45,20 @@ class IPSECKEY(dns.rdata.Rdata):
                  gateway, key):
         super(IPSECKEY, self).__init__(rdclass, rdtype)
         if gateway_type == 0:
-            if gateway != '.' and not gateway is None:
+            if gateway != '.' and gateway is not None:
                 raise SyntaxError('invalid gateway for gateway type 0')
             gateway = None
         elif gateway_type == 1:
             # check that it's OK
-            junk = dns.inet.inet_pton(dns.inet.AF_INET, gateway)
+            dns.inet.inet_pton(dns.inet.AF_INET, gateway)
         elif gateway_type == 2:
             # check that it's OK
-            junk = dns.inet.inet_pton(dns.inet.AF_INET6, gateway)
+            dns.inet.inet_pton(dns.inet.AF_INET6, gateway)
         elif gateway_type == 3:
             pass
         else:
-            raise SyntaxError('invalid IPSECKEY gateway type: %d' % gateway_type)
+            raise SyntaxError(
+                'invalid IPSECKEY gateway type: %d' % gateway_type)
         self.precedence = precedence
         self.gateway_type = gateway_type
         self.algorithm = algorithm
@@ -75,7 +80,8 @@ class IPSECKEY(dns.rdata.Rdata):
                                    self.algorithm, gateway,
                                    dns.rdata._base64ify(self.key))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         precedence = tok.get_uint8()
         gateway_type = tok.get_uint8()
         algorithm = tok.get_uint8()
@@ -90,15 +96,13 @@ class IPSECKEY(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        b64 = ''.join(chunks)
-        key = b64.decode('base64_codec')
+            chunks.append(t.value.encode())
+        b64 = b''.join(chunks)
+        key = base64.b64decode(b64)
         return cls(rdclass, rdtype, precedence, gateway_type, algorithm,
                    gateway, key)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         header = struct.pack("!BBB", self.precedence, self.gateway_type,
                              self.algorithm)
         file.write(header)
@@ -114,10 +118,11 @@ class IPSECKEY(dns.rdata.Rdata):
             raise ValueError('invalid gateway type')
         file.write(self.key)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         if rdlen < 3:
             raise dns.exception.FormError
-        header = struct.unpack('!BBB', wire[current : current + 3])
+        header = struct.unpack('!BBB', wire[current: current + 3])
         gateway_type = header[1]
         current += 3
         rdlen -= 3
@@ -125,12 +130,12 @@ class IPSECKEY(dns.rdata.Rdata):
             gateway = None
         elif gateway_type == 1:
             gateway = dns.inet.inet_ntop(dns.inet.AF_INET,
-                                         wire[current : current + 4])
+                                         wire[current: current + 4])
             current += 4
             rdlen -= 4
         elif gateway_type == 2:
             gateway = dns.inet.inet_ntop(dns.inet.AF_INET6,
-                                         wire[current : current + 16])
+                                         wire[current: current + 16])
             current += 16
             rdlen -= 16
         elif gateway_type == 3:
@@ -144,10 +149,8 @@ class IPSECKEY(dns.rdata.Rdata):
         return cls(rdclass, rdtype, header[0], gateway_type, header[2],
                    gateway, key)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f)
         wire1 = f.getvalue()
         f.seek(0)
@@ -156,4 +159,4 @@ class IPSECKEY(dns.rdata.Rdata):
         wire2 = f.getvalue()
         f.close()
 
-        return cmp(wire1, wire2)
+        return xcmp(wire1, wire2)
Index: dnspython-1.12.0/dns/rdtypes/IN/KX.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/KX.py
+++ dnspython-1.12.0/dns/rdtypes/IN/KX.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.mxbase
 
+
 class KX(dns.rdtypes.mxbase.UncompressedMX):
+
     """KX record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/IN/NAPTR.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/NAPTR.py
+++ dnspython-1.12.0/dns/rdtypes/IN/NAPTR.py
@@ -18,15 +18,25 @@ import struct
 import dns.exception
 import dns.name
 import dns.rdata
+from dns._compat import xrange, text_type
+from dns._compat import xcmp
+
 
 def _write_string(file, s):
     l = len(s)
     assert l < 256
-    byte = chr(l)
-    file.write(byte)
+    file.write(struct.pack('!B', l))
     file.write(s)
 
+
+def _sanitize(value):
+    if isinstance(value, text_type):
+        return value.encode()
+    return value
+
+
 class NAPTR(dns.rdata.Rdata):
+
     """NAPTR record
 
     @ivar order: order
@@ -49,11 +59,11 @@ class NAPTR(dns.rdata.Rdata):
     def __init__(self, rdclass, rdtype, order, preference, flags, service,
                  regexp, replacement):
         super(NAPTR, self).__init__(rdclass, rdtype)
+        self.flags = _sanitize(flags)
+        self.service = _sanitize(service)
+        self.regexp = _sanitize(regexp)
         self.order = order
         self.preference = preference
-        self.flags = flags
-        self.service = service
-        self.regexp = regexp
         self.replacement = replacement
 
     def to_text(self, origin=None, relativize=True, **kw):
@@ -63,9 +73,10 @@ class NAPTR(dns.rdata.Rdata):
                 dns.rdata._escapify(self.flags),
                 dns.rdata._escapify(self.service),
                 dns.rdata._escapify(self.regexp),
-                self.replacement)
+                replacement)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         order = tok.get_uint16()
         preference = tok.get_uint16()
         flags = tok.get_string()
@@ -77,9 +88,7 @@ class NAPTR(dns.rdata.Rdata):
         return cls(rdclass, rdtype, order, preference, flags, service,
                    regexp, replacement)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         two_ints = struct.pack("!HH", self.order, self.preference)
         file.write(two_ints)
         _write_string(file, self.flags)
@@ -87,18 +96,19 @@ class NAPTR(dns.rdata.Rdata):
         _write_string(file, self.regexp)
         self.replacement.to_wire(file, compress, origin)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (order, preference) = struct.unpack('!HH', wire[current : current + 4])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        (order, preference) = struct.unpack('!HH', wire[current: current + 4])
         current += 4
         rdlen -= 4
         strings = []
         for i in xrange(3):
-            l = ord(wire[current])
+            l = wire[current]
             current += 1
             rdlen -= 1
             if l > rdlen or rdlen < 0:
                 raise dns.exception.FormError
-            s = wire[current : current + l].unwrap()
+            s = wire[current: current + l].unwrap()
             current += l
             rdlen -= l
             strings.append(s)
@@ -106,27 +116,25 @@ class NAPTR(dns.rdata.Rdata):
                                                   current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             replacement = replacement.relativize(origin)
         return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
                    strings[2], replacement)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.replacement = self.replacement.choose_relativity(origin,
                                                               relativize)
 
     def _cmp(self, other):
         sp = struct.pack("!HH", self.order, self.preference)
         op = struct.pack("!HH", other.order, other.preference)
-        v = cmp(sp, op)
+        v = xcmp(sp, op)
         if v == 0:
-            v = cmp(self.flags, other.flags)
+            v = xcmp(self.flags, other.flags)
             if v == 0:
-                v = cmp(self.service, other.service)
+                v = xcmp(self.service, other.service)
                 if v == 0:
-                    v = cmp(self.regexp, other.regexp)
+                    v = xcmp(self.regexp, other.regexp)
                     if v == 0:
-                        v = cmp(self.replacement, other.replacement)
+                        v = xcmp(self.replacement, other.replacement)
         return v
Index: dnspython-1.12.0/dns/rdtypes/IN/NSAP.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/NSAP.py
+++ dnspython-1.12.0/dns/rdtypes/IN/NSAP.py
@@ -13,11 +13,16 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import binascii
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
 
+from dns._compat import xcmp
+
 class NSAP(dns.rdata.Rdata):
+
     """NSAP record.
 
     @ivar address: a NASP
@@ -31,8 +36,9 @@ class NSAP(dns.rdata.Rdata):
         self.address = address
 
     def to_text(self, origin=None, relativize=True, **kw):
-        return "0x%s" % self.address.encode('hex_codec')
+        return "0x%s" % binascii.hexlify(self.address).decode()
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         address = tok.get_string()
         t = tok.get_eol()
@@ -41,19 +47,16 @@ class NSAP(dns.rdata.Rdata):
         address = address[2:].replace('.', '')
         if len(address) % 2 != 0:
             raise dns.exception.SyntaxError('hexstring has odd length')
-        address = address.decode('hex_codec')
+        address = binascii.unhexlify(address.encode())
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(self.address)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         address = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        return cmp(self.address, other.address)
+        return xcmp(self.address, other.address)
Index: dnspython-1.12.0/dns/rdtypes/IN/NSAP_PTR.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/NSAP_PTR.py
+++ dnspython-1.12.0/dns/rdtypes/IN/NSAP_PTR.py
@@ -15,6 +15,8 @@
 
 import dns.rdtypes.nsbase
 
+
 class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS):
+
     """NSAP-PTR record"""
     pass
Index: dnspython-1.12.0/dns/rdtypes/IN/PX.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/PX.py
+++ dnspython-1.12.0/dns/rdtypes/IN/PX.py
@@ -18,8 +18,11 @@ import struct
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class PX(dns.rdata.Rdata):
+
     """PX record.
 
     @ivar preference: the preference value
@@ -43,7 +46,8 @@ class PX(dns.rdata.Rdata):
         mapx400 = self.mapx400.choose_relativity(origin, relativize)
         return '%d %s %s' % (self.preference, map822, mapx400)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         preference = tok.get_uint16()
         map822 = tok.get_name()
         map822 = map822.choose_relativity(origin, relativize)
@@ -52,46 +56,43 @@ class PX(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, preference, map822, mapx400)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         pref = struct.pack("!H", self.preference)
         file.write(pref)
         self.map822.to_wire(file, None, origin)
         self.mapx400.to_wire(file, None, origin)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (preference, ) = struct.unpack('!H', wire[current : current + 2])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        (preference, ) = struct.unpack('!H', wire[current: current + 2])
         current += 2
         rdlen -= 2
         (map822, cused) = dns.name.from_wire(wire[: current + rdlen],
-                                               current)
+                                             current)
         if cused > rdlen:
             raise dns.exception.FormError
         current += cused
         rdlen -= cused
-        if not origin is None:
+        if origin is not None:
             map822 = map822.relativize(origin)
         (mapx400, cused) = dns.name.from_wire(wire[: current + rdlen],
                                               current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             mapx400 = mapx400.relativize(origin)
         return cls(rdclass, rdtype, preference, map822, mapx400)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.map822 = self.map822.choose_relativity(origin, relativize)
         self.mapx400 = self.mapx400.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
         sp = struct.pack("!H", self.preference)
         op = struct.pack("!H", other.preference)
-        v = cmp(sp, op)
+        v = xcmp(sp, op)
         if v == 0:
-            v = cmp(self.map822, other.map822)
+            v = xcmp(self.map822, other.map822)
             if v == 0:
-                v = cmp(self.mapx400, other.mapx400)
+                v = xcmp(self.mapx400, other.mapx400)
         return v
Index: dnspython-1.12.0/dns/rdtypes/IN/SRV.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/SRV.py
+++ dnspython-1.12.0/dns/rdtypes/IN/SRV.py
@@ -18,8 +18,11 @@ import struct
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class SRV(dns.rdata.Rdata):
+
     """SRV record
 
     @ivar priority: the priority
@@ -46,7 +49,8 @@ class SRV(dns.rdata.Rdata):
         return '%d %d %d %s' % (self.priority, self.weight, self.port,
                                 target)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         priority = tok.get_uint16()
         weight = tok.get_uint16()
         port = tok.get_uint16()
@@ -55,35 +59,32 @@ class SRV(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, priority, weight, port, target)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         three_ints = struct.pack("!HHH", self.priority, self.weight, self.port)
         file.write(three_ints)
         self.target.to_wire(file, compress, origin)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (priority, weight, port) = struct.unpack('!HHH',
-                                                 wire[current : current + 6])
+                                                 wire[current: current + 6])
         current += 6
         rdlen -= 6
         (target, cused) = dns.name.from_wire(wire[: current + rdlen],
                                              current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             target = target.relativize(origin)
         return cls(rdclass, rdtype, priority, weight, port, target)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.target = self.target.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
         sp = struct.pack("!HHH", self.priority, self.weight, self.port)
         op = struct.pack("!HHH", other.priority, other.weight, other.port)
-        v = cmp(sp, op)
+        v = xcmp(sp, op)
         if v == 0:
-            v = cmp(self.target, other.target)
+            v = xcmp(self.target, other.target)
         return v
Index: dnspython-1.12.0/dns/rdtypes/IN/WKS.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/IN/WKS.py
+++ dnspython-1.12.0/dns/rdtypes/IN/WKS.py
@@ -18,11 +18,15 @@ import struct
 
 import dns.ipv4
 import dns.rdata
+from dns._compat import xrange
+from dns._compat import xcmp
 
 _proto_tcp = socket.getprotobyname('tcp')
 _proto_udp = socket.getprotobyname('udp')
 
+
 class WKS(dns.rdata.Rdata):
+
     """WKS record
 
     @ivar address: the address
@@ -39,26 +43,30 @@ class WKS(dns.rdata.Rdata):
         super(WKS, self).__init__(rdclass, rdtype)
         self.address = address
         self.protocol = protocol
-        self.bitmap = bitmap
+        if not isinstance(bitmap, bytearray):
+            self.bitmap = bytearray(bitmap)
+        else:
+            self.bitmap = bitmap
 
     def to_text(self, origin=None, relativize=True, **kw):
         bits = []
         for i in xrange(0, len(self.bitmap)):
-            byte = ord(self.bitmap[i])
+            byte = self.bitmap[i]
             for j in xrange(0, 8):
                 if byte & (0x80 >> j):
                     bits.append(str(i * 8 + j))
         text = ' '.join(bits)
         return '%s %d %s' % (self.address, self.protocol, text)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         address = tok.get_string()
         protocol = tok.get_string()
         if protocol.isdigit():
             protocol = int(protocol)
         else:
             protocol = socket.getprotobyname(protocol)
-        bitmap = []
+        bitmap = bytearray()
         while 1:
             token = tok.get().unescape()
             if token.is_eol_or_eof():
@@ -77,19 +85,18 @@ class WKS(dns.rdata.Rdata):
             l = len(bitmap)
             if l < i + 1:
                 for j in xrange(l, i + 1):
-                    bitmap.append('\x00')
-            bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (serv % 8)))
+                    bitmap.append(0)
+            bitmap[i] = bitmap[i] | (0x80 >> (serv % 8))
         bitmap = dns.rdata._truncate_bitmap(bitmap)
         return cls(rdclass, rdtype, address, protocol, bitmap)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         file.write(dns.ipv4.inet_aton(self.address))
         protocol = struct.pack('!B', self.protocol)
         file.write(protocol)
         file.write(self.bitmap)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         address = dns.ipv4.inet_ntoa(wire[current : current + 4])
         protocol, = struct.unpack('!B', wire[current + 4 : current + 5])
@@ -98,16 +105,14 @@ class WKS(dns.rdata.Rdata):
         bitmap = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, address, protocol, bitmap)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         sa = dns.ipv4.inet_aton(self.address)
         oa = dns.ipv4.inet_aton(other.address)
-        v = cmp(sa, oa)
+        v = xcmp(sa, oa)
         if v == 0:
             sp = struct.pack('!B', self.protocol)
             op = struct.pack('!B', other.protocol)
-            v = cmp(sp, op)
+            v = xcmp(sp, op)
             if v == 0:
-                v = cmp(self.bitmap, other.bitmap)
+                v = xcmp(self.bitmap, other.bitmap)
         return v
Index: dnspython-1.12.0/dns/rdtypes/dsbase.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/dsbase.py
+++ dnspython-1.12.0/dns/rdtypes/dsbase.py
@@ -14,11 +14,15 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
+from dns._compat import xcmp
+
 
 class DSBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like a DS record
 
     @ivar key_tag: the key tag
@@ -47,7 +51,8 @@ class DSBase(dns.rdata.Rdata):
                                 dns.rdata._hexify(self.digest,
                                                   chunksize=128))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         key_tag = tok.get_uint16()
         algorithm = tok.get_uint8()
         digest_type = tok.get_uint8()
@@ -58,20 +63,19 @@ class DSBase(dns.rdata.Rdata):
                 break
             if not t.is_identifier():
                 raise dns.exception.SyntaxError
-            chunks.append(t.value)
-        digest = ''.join(chunks)
-        digest = digest.decode('hex_codec')
+            chunks.append(t.value.encode())
+        digest = b''.join(chunks)
+        digest = binascii.unhexlify(digest)
         return cls(rdclass, rdtype, key_tag, algorithm, digest_type,
                    digest)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         header = struct.pack("!HBB", self.key_tag, self.algorithm,
                              self.digest_type)
         file.write(header)
         file.write(self.digest)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         header = struct.unpack("!HBB", wire[current : current + 4])
         current += 4
@@ -79,14 +83,12 @@ class DSBase(dns.rdata.Rdata):
         digest = wire[current : current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2], digest)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
         hs = struct.pack("!HBB", self.key_tag, self.algorithm,
                          self.digest_type)
         ho = struct.pack("!HBB", other.key_tag, other.algorithm,
                          other.digest_type)
-        v = cmp(hs, ho)
+        v = xcmp(hs, ho)
         if v == 0:
-            v = cmp(self.digest, other.digest)
+            v = xcmp(self.digest, other.digest)
         return v
Index: dnspython-1.12.0/dns/rdtypes/mxbase.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/mxbase.py
+++ dnspython-1.12.0/dns/rdtypes/mxbase.py
@@ -15,14 +15,17 @@
 
 """MX-like base classes."""
 
-import cStringIO
+from io import BytesIO
 import struct
 
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class MXBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like an MX record.
 
     @ivar preference: the preference value
@@ -41,6 +44,7 @@ class MXBase(dns.rdata.Rdata):
         exchange = self.exchange.choose_relativity(origin, relativize)
         return '%d %s' % (self.preference, exchange)
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         preference = tok.get_uint16()
         exchange = tok.get_name()
@@ -48,8 +52,6 @@ class MXBase(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, preference, exchange)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         pref = struct.pack("!H", self.preference)
         file.write(pref)
@@ -59,6 +61,7 @@ class MXBase(dns.rdata.Rdata):
         return struct.pack("!H", self.preference) + \
             self.exchange.to_digestable(origin)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         (preference, ) = struct.unpack('!H', wire[current : current + 2])
         current += 2
@@ -67,21 +70,19 @@ class MXBase(dns.rdata.Rdata):
                                                current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             exchange = exchange.relativize(origin)
         return cls(rdclass, rdtype, preference, exchange)
 
-    from_wire = classmethod(from_wire)
-
     def choose_relativity(self, origin = None, relativize = True):
         self.exchange = self.exchange.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
         sp = struct.pack("!H", self.preference)
         op = struct.pack("!H", other.preference)
-        v = cmp(sp, op)
+        v = xcmp(sp, op)
         if v == 0:
-            v = cmp(self.exchange, other.exchange)
+            v = xcmp(self.exchange, other.exchange)
         return v
 
 class UncompressedMX(MXBase):
@@ -93,7 +94,7 @@ class UncompressedMX(MXBase):
         super(UncompressedMX, self).to_wire(file, None, origin)
 
     def to_digestable(self, origin = None):
-        f = cStringIO.StringIO()
+        f = BytesIO()
         self.to_wire(f, None, origin)
         return f.getvalue()
 
Index: dnspython-1.12.0/dns/rdtypes/nsbase.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/nsbase.py
+++ dnspython-1.12.0/dns/rdtypes/nsbase.py
@@ -15,13 +15,16 @@
 
 """NS-like base classes."""
 
-import cStringIO
+from io import BytesIO
 
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import xcmp
+
 
 class NSBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like an NS record.
 
     @ivar target: the target name of the rdata
@@ -37,36 +40,34 @@ class NSBase(dns.rdata.Rdata):
         target = self.target.choose_relativity(origin, relativize)
         return str(target)
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
         target = tok.get_name()
         target = target.choose_relativity(origin, relativize)
         tok.get_eol()
         return cls(rdclass, rdtype, target)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         self.target.to_wire(file, compress, origin)
 
     def to_digestable(self, origin = None):
         return self.target.to_digestable(origin)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         (target, cused) = dns.name.from_wire(wire[: current + rdlen],
                                              current)
         if cused != rdlen:
             raise dns.exception.FormError
-        if not origin is None:
+        if origin is not None:
             target = target.relativize(origin)
         return cls(rdclass, rdtype, target)
 
-    from_wire = classmethod(from_wire)
-
     def choose_relativity(self, origin = None, relativize = True):
         self.target = self.target.choose_relativity(origin, relativize)
 
     def _cmp(self, other):
-        return cmp(self.target, other.target)
+        return xcmp(self.target, other.target)
 
 class UncompressedNS(NSBase):
     """Base class for rdata that is like an NS record, but whose name
@@ -76,7 +77,7 @@ class UncompressedNS(NSBase):
     def to_wire(self, file, compress = None, origin = None):
         super(UncompressedNS, self).to_wire(file, None, origin)
 
-    def to_digestable(self, origin = None):
-        f = cStringIO.StringIO()
+    def to_digestable(self, origin=None):
+        f = BytesIO()
         self.to_wire(f, None, origin)
         return f.getvalue()
Index: dnspython-1.12.0/dns/rdtypes/txtbase.py
===================================================================
--- dnspython-1.12.0.orig/dns/rdtypes/txtbase.py
+++ dnspython-1.12.0/dns/rdtypes/txtbase.py
@@ -15,11 +15,17 @@
 
 """TXT-like base class."""
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import binary_type, text_type
+from dns._compat import xcmp
+
 
 class TXTBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like a TXT record
 
     @ivar strings: the text strings
@@ -30,8 +36,8 @@ class TXTBase(dns.rdata.Rdata):
 
     def __init__(self, rdclass, rdtype, strings):
         super(TXTBase, self).__init__(rdclass, rdtype)
-        if isinstance(strings, str):
-            strings = [ strings ]
+        if isinstance(strings, text_type):
+            strings = [strings]
         self.strings = strings[:]
 
     def to_text(self, origin=None, relativize=True, **kw):
@@ -42,7 +48,8 @@ class TXTBase(dns.rdata.Rdata):
             prefix = ' '
         return txt
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         strings = []
         while 1:
             token = tok.get().unescape()
@@ -52,25 +59,27 @@ class TXTBase(dns.rdata.Rdata):
                 raise dns.exception.SyntaxError("expected a string")
             if len(token.value) > 255:
                 raise dns.exception.SyntaxError("string too long")
-            strings.append(token.value)
+            value = token.value
+            if isinstance(value, binary_type):
+                strings.append(value)
+            else:
+                strings.append(value.encode())
         if len(strings) == 0:
             raise dns.exception.UnexpectedEnd
         return cls(rdclass, rdtype, strings)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress = None, origin = None):
         for s in self.strings:
             l = len(s)
             assert l < 256
-            byte = chr(l)
-            file.write(byte)
+            file.write(struct.pack('!B', l))
             file.write(s)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
         strings = []
         while rdlen > 0:
-            l = ord(wire[current])
+            l = wire[current]
             current += 1
             rdlen -= 1
             if l > rdlen:
@@ -81,7 +90,5 @@ class TXTBase(dns.rdata.Rdata):
             strings.append(s)
         return cls(rdclass, rdtype, strings)
 
-    from_wire = classmethod(from_wire)
-
     def _cmp(self, other):
-        return cmp(self.strings, other.strings)
+        return xcmp(self.strings, other.strings)
Index: dnspython-1.12.0/dns/renderer.py
===================================================================
--- dnspython-1.12.0.orig/dns/renderer.py
+++ dnspython-1.12.0/dns/renderer.py
@@ -15,20 +15,25 @@
 
 """Help for building DNS wire format messages"""
 
-import cStringIO
+from io import BytesIO
 import struct
 import random
 import time
+import sys
 
 import dns.exception
 import dns.tsig
+from ._compat import long
+
 
 QUESTION = 0
 ANSWER = 1
 AUTHORITY = 2
 ADDITIONAL = 3
 
+
 class Renderer(object):
+
     """Helper class for building DNS wire-format messages.
 
     Most applications can use the higher-level L{dns.message.Message}
@@ -51,7 +56,7 @@ class Renderer(object):
         wire = r.get_wire()
 
     @ivar output: where rendering is written
-    @type output: cStringIO.StringIO object
+    @type output: BytesIO object
     @ivar id: the message id
     @type id: int
     @ivar flags: the message flags
@@ -86,7 +91,7 @@ class Renderer(object):
         @type origin: dns.name.Namem or None.
         """
 
-        self.output = cStringIO.StringIO()
+        self.output = BytesIO()
         if id is None:
             self.id = random.randint(0, 65535)
         else:
@@ -97,7 +102,7 @@ class Renderer(object):
         self.compress = {}
         self.section = QUESTION
         self.counts = [0, 0, 0, 0]
-        self.output.write('\x00' * 12)
+        self.output.write(b'\x00' * 12)
         self.mac = ''
 
     def _rollback(self, where):
@@ -112,7 +117,7 @@ class Renderer(object):
         self.output.seek(where)
         self.output.truncate()
         keys_to_delete = []
-        for k, v in self.compress.iteritems():
+        for k, v in self.compress.items():
             if v >= where:
                 keys_to_delete.append(k)
         for k in keys_to_delete:
@@ -218,13 +223,13 @@ class Renderer(object):
         """
 
         # make sure the EDNS version in ednsflags agrees with edns
-        ednsflags &= 0xFF00FFFFL
+        ednsflags &= long(0xFF00FFFF)
         ednsflags |= (edns << 16)
         self._set_section(ADDITIONAL)
         before = self.output.tell()
         self.output.write(struct.pack('!BHHIH', 0, dns.rdatatype.OPT, payload,
                                       ednsflags, 0))
-        if not options is None:
+        if options is not None:
             lstart = self.output.tell()
             for opt in options:
                 stuff = struct.pack("!HH", opt.otype, 0)
Index: dnspython-1.12.0/dns/resolver.py
===================================================================
--- dnspython-1.12.0.orig/dns/resolver.py
+++ dnspython-1.12.0/dns/resolver.py
@@ -40,6 +40,8 @@ import dns.rdataclass
 import dns.rdatatype
 import dns.reversename
 
+from ._compat import xrange, string_types
+
 if sys.platform == 'win32':
     import _winreg
 
@@ -110,6 +112,7 @@ class Answer(object):
     @ivar canonical_name: The canonical name of the query name
     @type canonical_name: dns.name.Name object
     """
+
     def __init__(self, qname, rdtype, rdclass, response,
                  raise_on_no_answer=True):
         self.qname = qname
@@ -153,7 +156,7 @@ class Answer(object):
                 # of qname.
                 try:
                     srrset = response.find_rrset(response.authority, qname,
-                                                rdclass, dns.rdatatype.SOA)
+                                                 rdclass, dns.rdatatype.SOA)
                     if min_ttl == -1 or srrset.ttl < min_ttl:
                         min_ttl = srrset.ttl
                     if srrset[0].minimum < min_ttl:
@@ -198,7 +201,9 @@ class Answer(object):
     def __delslice__(self, i, j):
         del self.rrset[i:j]
 
+
 class Cache(object):
+
     """Simple DNS answer cache.
 
     @ivar data: A dictionary of cached data
@@ -230,7 +235,7 @@ class Cache(object):
         now = time.time()
         if self.next_cleaning <= now:
             keys_to_delete = []
-            for (k, v) in self.data.iteritems():
+            for (k, v) in self.data.items():
                 if v.expiration <= now:
                     keys_to_delete.append(k)
             for k in keys_to_delete:
@@ -285,8 +290,8 @@ class Cache(object):
 
         try:
             self.lock.acquire()
-            if not key is None:
-                if self.data.has_key(key):
+            if key is not None:
+                if key in self.data:
                     del self.data[key]
             else:
                 self.data = {}
@@ -294,9 +299,12 @@ class Cache(object):
         finally:
             self.lock.release()
 
+
 class LRUCacheNode(object):
+
     """LRUCache node.
     """
+
     def __init__(self, key, value):
         self.key = key
         self.value = value
@@ -319,7 +327,9 @@ class LRUCacheNode(object):
         self.next.prev = self.prev
         self.prev.next = self.next
 
+
 class LRUCache(object):
+
     """Bounded least-recently-used DNS answer cache.
 
     This cache is better than the simple cache (above) if you're
@@ -339,7 +349,8 @@ class LRUCache(object):
     def __init__(self, max_size=100000):
         """Initialize a DNS cache.
 
-        @param max_size: The maximum number of nodes to cache; the default is 100000.  Must be > 1.
+        @param max_size: The maximum number of nodes to cache; the default is
+        100000. Must be > 1.
         @type max_size: int
         """
         self.data = {}
@@ -387,7 +398,7 @@ class LRUCache(object):
         try:
             self.lock.acquire()
             node = self.data.get(key)
-            if not node is None:
+            if node is not None:
                 node.unlink()
                 del self.data[node.key]
             while len(self.data) >= self.max_size:
@@ -411,9 +422,9 @@ class LRUCache(object):
         """
         try:
             self.lock.acquire()
-            if not key is None:
+            if key is not None:
                 node = self.data.get(key)
-                if not node is None:
+                if node is not None:
                     node.unlink()
                     del self.data[node.key]
             else:
@@ -427,7 +438,9 @@ class LRUCache(object):
         finally:
             self.lock.release()
 
+
 class Resolver(object):
+
     """DNS stub resolver
 
     @ivar domain: The domain of this host
@@ -461,7 +474,8 @@ class Resolver(object):
     @type ednsflags: int
     @ivar payload: The EDNS payload size.  The default is 0.
     @type payload: int
-    @ivar flags: The message flags to use.  The default is None (i.e. not overwritten)
+    @ivar flags: The message flags to use.  The default is None (i.e. not
+    overwritten)
     @type flags: int
     @ivar cache: The cache to use.  The default is None.
     @type cache: dns.resolver.Cache object
@@ -469,6 +483,7 @@ class Resolver(object):
     The default is 'false'.
     @type retry_servfail: bool
     """
+
     def __init__(self, filename='/etc/resolv.conf', configure=True):
         """Initialize a resolver instance.
 
@@ -515,7 +530,7 @@ class Resolver(object):
         """Process f as a file in the /etc/resolv.conf format.  If f is
         a string, it is used as the name of the file to open; otherwise it
         is treated as the file itself."""
-        if isinstance(f, str) or isinstance(f, unicode):
+        if isinstance(f, string_types):
             try:
                 f = open(f, 'r')
             except IOError:
@@ -571,7 +586,7 @@ class Resolver(object):
         split_char = self._determine_split_char(nameservers)
         ns_list = nameservers.split(split_char)
         for ns in ns_list:
-            if not ns in self.nameservers:
+            if ns not in self.nameservers:
                 self.nameservers.append(ns)
 
     def _config_win32_domain(self, domain):
@@ -586,7 +601,7 @@ class Resolver(object):
         split_char = self._determine_split_char(search)
         search_list = search.split(split_char)
         for s in search_list:
-            if not s in self.search:
+            if s not in self.search:
                 self.search.append(dns.name.from_text(s))
 
     def _config_win32_fromkey(self, key):
@@ -669,59 +684,59 @@ class Resolver(object):
             lm.Close()
 
     def _win32_is_nic_enabled(self, lm, guid, interface_key):
-         # Look in the Windows Registry to determine whether the network
-         # interface corresponding to the given guid is enabled.
-         #
-         # (Code contributed by Paul Marks, thanks!)
-         #
-         try:
-             # This hard-coded location seems to be consistent, at least
-             # from Windows 2000 through Vista.
-             connection_key = _winreg.OpenKey(
-                 lm,
-                 r'SYSTEM\CurrentControlSet\Control\Network'
-                 r'\{4D36E972-E325-11CE-BFC1-08002BE10318}'
-                 r'\%s\Connection' % guid)
-
-             try:
-                 # The PnpInstanceID points to a key inside Enum
-                 (pnp_id, ttype) = _winreg.QueryValueEx(
-                     connection_key, 'PnpInstanceID')
-
-                 if ttype != _winreg.REG_SZ:
-                     raise ValueError
-
-                 device_key = _winreg.OpenKey(
-                     lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)
-
-                 try:
-                     # Get ConfigFlags for this device
-                     (flags, ttype) = _winreg.QueryValueEx(
-                         device_key, 'ConfigFlags')
-
-                     if ttype != _winreg.REG_DWORD:
-                         raise ValueError
-
-                     # Based on experimentation, bit 0x1 indicates that the
-                     # device is disabled.
-                     return not (flags & 0x1)
-
-                 finally:
-                     device_key.Close()
-             finally:
-                 connection_key.Close()
-         except (EnvironmentError, ValueError):
-             # Pre-vista, enabled interfaces seem to have a non-empty
-             # NTEContextList; this was how dnspython detected enabled
-             # nics before the code above was contributed.  We've retained
-             # the old method since we don't know if the code above works
-             # on Windows 95/98/ME.
-             try:
-                 (nte, ttype) = _winreg.QueryValueEx(interface_key,
-                                                     'NTEContextList')
-                 return nte is not None
-             except WindowsError:
-                 return False
+        # Look in the Windows Registry to determine whether the network
+        # interface corresponding to the given guid is enabled.
+        #
+        # (Code contributed by Paul Marks, thanks!)
+        #
+        try:
+            # This hard-coded location seems to be consistent, at least
+            # from Windows 2000 through Vista.
+            connection_key = _winreg.OpenKey(
+                lm,
+                r'SYSTEM\CurrentControlSet\Control\Network'
+                r'\{4D36E972-E325-11CE-BFC1-08002BE10318}'
+                r'\%s\Connection' % guid)
+
+            try:
+                # The PnpInstanceID points to a key inside Enum
+                (pnp_id, ttype) = _winreg.QueryValueEx(
+                    connection_key, 'PnpInstanceID')
+
+                if ttype != _winreg.REG_SZ:
+                    raise ValueError
+
+                device_key = _winreg.OpenKey(
+                    lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)
+
+                try:
+                    # Get ConfigFlags for this device
+                    (flags, ttype) = _winreg.QueryValueEx(
+                        device_key, 'ConfigFlags')
+
+                    if ttype != _winreg.REG_DWORD:
+                        raise ValueError
+
+                    # Based on experimentation, bit 0x1 indicates that the
+                    # device is disabled.
+                    return not (flags & 0x1)
+
+                finally:
+                    device_key.Close()
+            finally:
+                connection_key.Close()
+        except (EnvironmentError, ValueError):
+            # Pre-vista, enabled interfaces seem to have a non-empty
+            # NTEContextList; this was how dnspython detected enabled
+            # nics before the code above was contributed.  We've retained
+            # the old method since we don't know if the code above works
+            # on Windows 95/98/ME.
+            try:
+                (nte, ttype) = _winreg.QueryValueEx(interface_key,
+                                                    'NTEContextList')
+                return nte is not None
+            except WindowsError:
+                return False
 
     def _compute_timeout(self, start):
         now = time.time()
@@ -756,7 +771,8 @@ class Resolver(object):
         @type rdclass: int or string
         @param tcp: use TCP to make the query (default is False).
         @type tcp: bool
-        @param source: bind to this IP address (defaults to machine default IP).
+        @param source: bind to this IP address (defaults to machine default
+        IP).
         @type source: IP address in dotted quad notation
         @param raise_on_no_answer: raise NoAnswer if there's no answer
         (defaults is True).
@@ -773,13 +789,13 @@ class Resolver(object):
         @raises NoNameservers: no non-broken nameservers are available to
         answer the question."""
 
-        if isinstance(qname, (str, unicode)):
+        if isinstance(qname, string_types):
             qname = dns.name.from_text(qname, None)
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
         if dns.rdatatype.is_metatype(rdtype):
             raise NoMetaqueries
-        if isinstance(rdclass, (str, unicode)):
+        if isinstance(rdclass, string_types):
             rdclass = dns.rdataclass.from_text(rdclass)
         if dns.rdataclass.is_metaclass(rdclass):
             raise NoMetaqueries
@@ -799,13 +815,13 @@ class Resolver(object):
         for qname in qnames_to_try:
             if self.cache:
                 answer = self.cache.get((qname, rdtype, rdclass))
-                if not answer is None:
+                if answer is not None:
                     if answer.rrset is None and raise_on_no_answer:
                         raise NoAnswer
                     else:
                         return answer
             request = dns.message.make_query(qname, rdtype, rdclass)
-            if not self.keyname is None:
+            if self.keyname is not None:
                 request.use_tsig(self.keyring, self.keyname,
                                  algorithm=self.keyalgorithm)
             request.use_edns(self.edns, self.ednsflags, self.payload)
@@ -878,7 +894,7 @@ class Resolver(object):
                     if rcode == dns.rcode.YXDOMAIN:
                         raise YXDOMAIN
                     if rcode == dns.rcode.NOERROR or \
-                           rcode == dns.rcode.NXDOMAIN:
+                            rcode == dns.rcode.NXDOMAIN:
                         break
                     #
                     # We got a response, but we're not happy with the
@@ -888,7 +904,7 @@ class Resolver(object):
                     if rcode != dns.rcode.SERVFAIL or not self.retry_servfail:
                         nameservers.remove(nameserver)
                     response = None
-                if not response is None:
+                if response is not None:
                     break
                 #
                 # All nameservers failed!
@@ -961,6 +977,7 @@ class Resolver(object):
 
 default_resolver = None
 
+
 def get_default_resolver():
     """Get the default resolver, initializing it if necessary."""
     global default_resolver
@@ -968,6 +985,7 @@ def get_default_resolver():
         default_resolver = Resolver()
     return default_resolver
 
+
 def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
           tcp=False, source=None, raise_on_no_answer=True,
           source_port=0):
@@ -980,6 +998,7 @@ def query(qname, rdtype=dns.rdatatype.A,
     return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
                                         raise_on_no_answer, source_port)
 
+
 def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
     """Find the name of the zone which contains the specified name.
 
@@ -993,7 +1012,7 @@ def zone_for_name(name, rdclass=dns.rdat
     @type resolver: dns.resolver.Resolver object or None
     @rtype: dns.name.Name"""
 
-    if isinstance(name, (str, unicode)):
+    if isinstance(name, string_types):
         name = dns.name.from_text(name, dns.name.root)
     if resolver is None:
         resolver = get_default_resolver()
@@ -1018,9 +1037,9 @@ def zone_for_name(name, rdclass=dns.rdat
 #
 
 _protocols_for_socktype = {
-    socket.SOCK_DGRAM : [socket.SOL_UDP],
-    socket.SOCK_STREAM : [socket.SOL_TCP],
-    }
+    socket.SOCK_DGRAM: [socket.SOL_UDP],
+    socket.SOCK_STREAM: [socket.SOL_TCP],
+}
 
 _resolver = None
 _original_getaddrinfo = socket.getaddrinfo
@@ -1030,9 +1049,10 @@ _original_gethostbyname = socket.gethost
 _original_gethostbyname_ex = socket.gethostbyname_ex
 _original_gethostbyaddr = socket.gethostbyaddr
 
+
 def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
                  proto=0, flags=0):
-    if flags & (socket.AI_ADDRCONFIG|socket.AI_V4MAPPED) != 0:
+    if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0:
         raise NotImplementedError
     if host is None and service is None:
         raise socket.gaierror(socket.EAI_NONAME)
@@ -1067,7 +1087,6 @@ def _getaddrinfo(host=None, service=None
         except:
             if flags & socket.AI_NUMERICHOST == 0:
                 try:
-                    qname = None
                     if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
                         v6 = _resolver.query(host, dns.rdatatype.AAAA,
                                              raise_on_no_answer=False)
@@ -1130,6 +1149,7 @@ def _getaddrinfo(host=None, service=None
         raise socket.gaierror(socket.EAI_NONAME)
     return tuples
 
+
 def _getnameinfo(sockaddr, flags=0):
     host = sockaddr[0]
     port = sockaddr[1]
@@ -1169,28 +1189,32 @@ def _getnameinfo(sockaddr, flags=0):
         service = socket.getservbyport(port, pname)
     return (hostname, service)
 
+
 def _getfqdn(name=None):
     if name is None:
         name = socket.gethostname()
     return _getnameinfo(_getaddrinfo(name, 80)[0][4])[0]
 
+
 def _gethostbyname(name):
     return _gethostbyname_ex(name)[2][0]
 
+
 def _gethostbyname_ex(name):
     aliases = []
     addresses = []
     tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
-                         socket.SOL_TCP, socket.AI_CANONNAME)
+                          socket.SOL_TCP, socket.AI_CANONNAME)
     canonical = tuples[0][3]
     for item in tuples:
         addresses.append(item[4][0])
     # XXX we just ignore aliases
     return (canonical, aliases, addresses)
 
+
 def _gethostbyaddr(ip):
     try:
-        addr = dns.ipv6.inet_aton(ip)
+        dns.ipv6.inet_aton(ip)
         sockaddr = (ip, 80, 0, 0)
         family = socket.AF_INET6
     except:
@@ -1207,6 +1231,7 @@ def _gethostbyaddr(ip):
     # XXX we just ignore aliases
     return (canonical, aliases, addresses)
 
+
 def override_system_resolver(resolver=None):
     """Override the system resolver routines in the socket module with
     versions which use dnspython's resolver.
@@ -1232,6 +1257,7 @@ def override_system_resolver(resolver=No
     socket.gethostbyname_ex = _gethostbyname_ex
     socket.gethostbyaddr = _gethostbyaddr
 
+
 def restore_system_resolver():
     """Undo the effects of override_system_resolver().
     """
Index: dnspython-1.12.0/dns/reversename.py
===================================================================
--- dnspython-1.12.0.orig/dns/reversename.py
+++ dnspython-1.12.0/dns/reversename.py
@@ -21,6 +21,9 @@
 @type ipv6_reverse_domain: dns.name.Name object
 """
 
+import binascii
+import sys
+
 import dns.name
 import dns.ipv6
 import dns.ipv4
@@ -28,6 +31,7 @@ import dns.ipv4
 ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.')
 ipv6_reverse_domain = dns.name.from_text('ip6.arpa.')
 
+
 def from_address(text):
     """Convert an IPv4 or IPv6 address in textual form into a Name object whose
     value is the reverse-map domain name of the address.
@@ -39,17 +43,22 @@ def from_address(text):
     try:
         v6 = dns.ipv6.inet_aton(text)
         if dns.ipv6.is_mapped(v6):
-            parts = ['%d' % ord(byte) for byte in v6[12:]]
+            if sys.version_info >= (3,):
+                parts = ['%d' % byte for byte in v6[12:]]
+            else:
+                parts = ['%d' % ord(byte) for byte in v6[12:]]
             origin = ipv4_reverse_domain
         else:
-            parts = list(v6.encode('hex_codec'))
+            parts = [x for x in str(binascii.hexlify(v6).decode())]
             origin = ipv6_reverse_domain
     except:
-        parts = ['%d' % ord(byte) for byte in dns.ipv4.inet_aton(text)]
+        parts = ['%d' %
+                 byte for byte in bytearray(dns.ipv4.inet_aton(text))]
         origin = ipv4_reverse_domain
     parts.reverse()
     return dns.name.from_text('.'.join(parts), origin=origin)
 
+
 def to_address(name):
     """Convert a reverse map domain name into textual address form.
     @param name: an IPv4 or IPv6 address in reverse-map form.
@@ -60,7 +69,7 @@ def to_address(name):
         name = name.relativize(ipv4_reverse_domain)
         labels = list(name.labels)
         labels.reverse()
-        text = '.'.join(labels)
+        text = b'.'.join(labels)
         # run through inet_aton() to check syntax and make pretty.
         return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
     elif name.is_subdomain(ipv6_reverse_domain):
@@ -71,9 +80,9 @@ def to_address(name):
         i = 0
         l = len(labels)
         while i < l:
-            parts.append(''.join(labels[i:i+4]))
+            parts.append(b''.join(labels[i:i + 4]))
             i += 4
-        text = ':'.join(parts)
+        text = b':'.join(parts)
         # run through inet_aton() to check syntax and make pretty.
         return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
     else:
Index: dnspython-1.12.0/dns/rrset.py
===================================================================
--- dnspython-1.12.0.orig/dns/rrset.py
+++ dnspython-1.12.0/dns/rrset.py
@@ -15,12 +15,16 @@
 
 """DNS RRsets (an RRset is a named rdataset)"""
 
+
 import dns.name
 import dns.rdataset
 import dns.rdataclass
 import dns.renderer
+from ._compat import string_types
+
 
 class RRset(dns.rdataset.Rdataset):
+
     """A DNS RRset (named rdataset).
 
     RRset inherits from Rdataset, and RRsets can be treated as
@@ -51,7 +55,7 @@ class RRset(dns.rdataset.Rdataset):
             ctext = ''
         else:
             ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
-        if not self.deleting is None:
+        if self.deleting is not None:
             dtext = ' delete=' + dns.rdataclass.to_text(self.deleting)
         else:
             dtext = ''
@@ -122,11 +126,11 @@ def from_text_list(name, ttl, rdclass, r
     @rtype: dns.rrset.RRset object
     """
 
-    if isinstance(name, (str, unicode)):
+    if isinstance(name, string_types):
         name = dns.name.from_text(name, None)
-    if isinstance(rdclass, (str, unicode)):
+    if isinstance(rdclass, string_types):
         rdclass = dns.rdataclass.from_text(rdclass)
-    if isinstance(rdtype, (str, unicode)):
+    if isinstance(rdtype, string_types):
         rdtype = dns.rdatatype.from_text(rdtype)
     r = RRset(name, rdclass, rdtype)
     r.update_ttl(ttl)
@@ -135,6 +139,7 @@ def from_text_list(name, ttl, rdclass, r
         r.add(rd)
     return r
 
+
 def from_text(name, ttl, rdclass, rdtype, *text_rdatas):
     """Create an RRset with the specified name, TTL, class, and type and with
     the specified rdatas in text format.
@@ -144,6 +149,7 @@ def from_text(name, ttl, rdclass, rdtype
 
     return from_text_list(name, ttl, rdclass, rdtype, text_rdatas)
 
+
 def from_rdata_list(name, ttl, rdatas):
     """Create an RRset with the specified name and TTL, and with
     the specified list of rdata objects.
@@ -151,7 +157,7 @@ def from_rdata_list(name, ttl, rdatas):
     @rtype: dns.rrset.RRset object
     """
 
-    if isinstance(name, (str, unicode)):
+    if isinstance(name, string_types):
         name = dns.name.from_text(name, None)
 
     if len(rdatas) == 0:
@@ -161,10 +167,10 @@ def from_rdata_list(name, ttl, rdatas):
         if r is None:
             r = RRset(name, rd.rdclass, rd.rdtype)
             r.update_ttl(ttl)
-            first_time = False
         r.add(rd)
     return r
 
+
 def from_rdata(name, ttl, *rdatas):
     """Create an RRset with the specified name and TTL, and with
     the specified rdata objects.
Index: dnspython-1.12.0/dns/set.py
===================================================================
--- dnspython-1.12.0.orig/dns/set.py
+++ dnspython-1.12.0/dns/set.py
@@ -15,7 +15,9 @@
 
 """A simple Set class."""
 
+
 class Set(object):
+
     """A simple set class.
 
     Sets are not in Python until 2.3, and rdata are not immutable so
@@ -35,7 +37,7 @@ class Set(object):
         """
 
         self.items = []
-        if not items is None:
+        if items is not None:
             for item in items:
                 self.add(item)
 
@@ -44,7 +46,7 @@ class Set(object):
 
     def add(self, item):
         """Add an item to the set."""
-        if not item in self.items:
+        if item not in self.items:
             self.items.append(item)
 
     def remove(self, item):
@@ -208,10 +210,10 @@ class Set(object):
         # Yes, this is inefficient but the sets we're dealing with are
         # usually quite small, so it shouldn't hurt too much.
         for item in self.items:
-            if not item in other.items:
+            if item not in other.items:
                 return False
         for item in other.items:
-            if not item in self.items:
+            if item not in self.items:
                 return False
         return True
 
@@ -245,7 +247,7 @@ class Set(object):
         if not isinstance(other, Set):
             raise ValueError('other must be a Set instance')
         for item in self.items:
-            if not item in other.items:
+            if item not in other.items:
                 return False
         return True
 
@@ -258,6 +260,6 @@ class Set(object):
         if not isinstance(other, Set):
             raise ValueError('other must be a Set instance')
         for item in other.items:
-            if not item in self.items:
+            if item not in self.items:
                 return False
         return True
Index: dnspython-1.12.0/dns/tokenizer.py
===================================================================
--- dnspython-1.12.0.orig/dns/tokenizer.py
+++ dnspython-1.12.0/dns/tokenizer.py
@@ -15,23 +15,24 @@
 
 """Tokenize DNS master file format"""
 
-import cStringIO
+from io import StringIO
 import sys
 
 import dns.exception
 import dns.name
 import dns.ttl
+from ._compat import long, text_type, binary_type
 
 _DELIMITERS = {
-    ' ' : True,
-    '\t' : True,
-    '\n' : True,
-    ';' : True,
-    '(' : True,
-    ')' : True,
-    '"' : True }
+    ' ': True,
+    '\t': True,
+    '\n': True,
+    ';': True,
+    '(': True,
+    ')': True,
+    '"': True}
 
-_QUOTING_DELIMITERS = { '"' : True }
+_QUOTING_DELIMITERS = {'"': True}
 
 EOF = 0
 EOL = 1
@@ -155,7 +156,9 @@ class Token(object):
         else:
             raise IndexError
 
+
 class Tokenizer(object):
+
     """A DNS master file format tokenizer.
 
     A token is a (type, value) tuple, where I{type} is an int, and
@@ -197,8 +200,12 @@ class Tokenizer(object):
         @type filename: string
         """
 
-        if isinstance(f, str):
-            f = cStringIO.StringIO(f)
+        if isinstance(f, text_type):
+            f = StringIO(f)
+            if filename is None:
+                filename = '<string>'
+        elif isinstance(f, binary_type):
+            f = StringIO(f.decode())
             if filename is None:
                 filename = '<string>'
         else:
@@ -257,7 +264,7 @@ class Tokenizer(object):
         @raises UngetBufferFull: there is already an ungotten char
         """
 
-        if not self.ungotten_char is None:
+        if self.ungotten_char is not None:
             raise UngetBufferFull
         self.ungotten_char = c
 
@@ -281,7 +288,7 @@ class Tokenizer(object):
                     return skipped
             skipped += 1
 
-    def get(self, want_leading = False, want_comment = False):
+    def get(self, want_leading=False, want_comment=False):
         """Get the next token.
 
         @param want_leading: If True, return a WHITESPACE token if the
@@ -295,7 +302,7 @@ class Tokenizer(object):
         @raises dns.exception.SyntaxError: input was badly formed
         """
 
-        if not self.ungotten_token is None:
+        if self.ungotten_token is not None:
             token = self.ungotten_token
             self.ungotten_token = None
             if token.is_whitespace():
@@ -352,7 +359,8 @@ class Tokenizer(object):
                             return Token(COMMENT, token)
                         elif c == '':
                             if self.multiline:
-                                raise dns.exception.SyntaxError('unbalanced parentheses')
+                                raise dns.exception.SyntaxError(
+                                    'unbalanced parentheses')
                             return Token(EOF)
                         elif self.multiline:
                             self.skip_whitespace()
@@ -415,7 +423,7 @@ class Tokenizer(object):
         @raises UngetBufferFull: there is already an ungotten token
         """
 
-        if not self.ungotten_token is None:
+        if self.ungotten_token is not None:
             raise UngetBufferFull
         self.ungotten_token = token
 
@@ -429,6 +437,8 @@ class Tokenizer(object):
             raise StopIteration
         return token
 
+    __next__ = next
+
     def __iter__(self):
         return self
 
@@ -458,7 +468,8 @@ class Tokenizer(object):
 
         value = self.get_int()
         if value < 0 or value > 255:
-            raise dns.exception.SyntaxError('%d is not an unsigned 8-bit integer' % value)
+            raise dns.exception.SyntaxError(
+                '%d is not an unsigned 8-bit integer' % value)
         return value
 
     def get_uint16(self):
@@ -471,7 +482,8 @@ class Tokenizer(object):
 
         value = self.get_int()
         if value < 0 or value > 65535:
-            raise dns.exception.SyntaxError('%d is not an unsigned 16-bit integer' % value)
+            raise dns.exception.SyntaxError(
+                '%d is not an unsigned 16-bit integer' % value)
         return value
 
     def get_uint32(self):
@@ -488,8 +500,9 @@ class Tokenizer(object):
         if not token.value.isdigit():
             raise dns.exception.SyntaxError('expecting an integer')
         value = long(token.value)
-        if value < 0 or value > 4294967296L:
-            raise dns.exception.SyntaxError('%d is not an unsigned 32-bit integer' % value)
+        if value < 0 or value > long(4294967296):
+            raise dns.exception.SyntaxError(
+                '%d is not an unsigned 32-bit integer' % value)
         return value
 
     def get_string(self, origin=None):
@@ -537,7 +550,9 @@ class Tokenizer(object):
 
         token = self.get()
         if not token.is_eol_or_eof():
-            raise dns.exception.SyntaxError('expected EOL or EOF, got %d "%s"' % (token.ttype, token.value))
+            raise dns.exception.SyntaxError(
+                'expected EOL or EOF, got %d "%s"' % (token.ttype,
+                                                      token.value))
         return token.value
 
     def get_ttl(self):
Index: dnspython-1.12.0/dns/tsig.py
===================================================================
--- dnspython-1.12.0.orig/dns/tsig.py
+++ dnspython-1.12.0/dns/tsig.py
@@ -23,6 +23,7 @@ import dns.exception
 import dns.hash
 import dns.rdataclass
 import dns.name
+from ._compat import long, string_types
 
 class BadTime(dns.exception.DNSException):
     """Raised if the current time is not within the TSIG's validity time."""
@@ -68,6 +69,7 @@ BADKEY = 17
 BADTIME = 18
 BADTRUNC = 22
 
+
 def sign(wire, keyname, secret, time, fudge, original_id, error,
          other_data, request_mac, ctx=None, multi=False, first=True,
          algorithm=default_algorithm):
@@ -93,9 +95,9 @@ def sign(wire, keyname, secret, time, fu
         ctx.update(keyname.to_digestable())
         ctx.update(struct.pack('!H', dns.rdataclass.ANY))
         ctx.update(struct.pack('!I', 0))
-    long_time = time + 0L
-    upper_time = (long_time >> 32) & 0xffffL
-    lower_time = long_time & 0xffffffffL
+    long_time = time + long(0)
+    upper_time = (long_time >> 32) & long(0xffff)
+    lower_time = long_time & long(0xffffffff)
     time_mac = struct.pack('!HIH', upper_time, lower_time, fudge)
     pre_mac = algorithm_name + time_mac
     ol = len(other_data)
@@ -119,12 +121,14 @@ def sign(wire, keyname, secret, time, fu
         ctx = None
     return (tsig_rdata, mac, ctx)
 
+
 def hmac_md5(wire, keyname, secret, time, fudge, original_id, error,
              other_data, request_mac, ctx=None, multi=False, first=True,
              algorithm=default_algorithm):
     return sign(wire, keyname, secret, time, fudge, original_id, error,
                 other_data, request_mac, ctx, multi, first, algorithm)
 
+
 def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
              tsig_rdlen, ctx=None, multi=False, first=True):
     """Validate the specified TSIG rdata against the other input parameters.
@@ -144,13 +148,13 @@ def validate(wire, keyname, secret, now,
     (aname, used) = dns.name.from_wire(wire, current)
     current = current + used
     (upper_time, lower_time, fudge, mac_size) = \
-                 struct.unpack("!HIHH", wire[current:current + 10])
-    time = ((upper_time + 0L) << 32) + (lower_time + 0L)
+        struct.unpack("!HIHH", wire[current:current + 10])
+    time = ((upper_time + long(0)) << 32) + (lower_time + long(0))
     current += 10
     mac = wire[current:current + mac_size]
     current += mac_size
     (original_id, error, other_size) = \
-                  struct.unpack("!HHH", wire[current:current + 6])
+        struct.unpack("!HHH", wire[current:current + 6])
     current += 6
     other_data = wire[current:current + other_size]
     current += other_size
@@ -178,23 +182,6 @@ def validate(wire, keyname, secret, now,
         raise BadSignature
     return ctx
 
-_hashes = None
-
-def _maybe_add_hash(tsig_alg, hash_alg):
-    try:
-        _hashes[tsig_alg] = dns.hash.get(hash_alg)
-    except KeyError:
-        pass
-
-def _setup_hashes():
-    global _hashes
-    _hashes = {}
-    _maybe_add_hash(HMAC_SHA224, 'SHA224')
-    _maybe_add_hash(HMAC_SHA256, 'SHA256')
-    _maybe_add_hash(HMAC_SHA384, 'SHA384')
-    _maybe_add_hash(HMAC_SHA512, 'SHA512')
-    _maybe_add_hash(HMAC_SHA1, 'SHA1')
-    _maybe_add_hash(HMAC_MD5, 'MD5')
 
 def get_algorithm(algorithm):
     """Returns the wire format string and the hash module to use for the
@@ -204,24 +191,16 @@ def get_algorithm(algorithm):
     @raises NotImplementedError: I{algorithm} is not supported
     """
 
-    global _hashes
-    if _hashes is None:
-        _setup_hashes()
-
-    if isinstance(algorithm, (str, unicode)):
+    if isinstance(algorithm, string_types):
         algorithm = dns.name.from_text(algorithm)
 
-    if sys.hexversion < 0x02050200 and \
-       (algorithm == HMAC_SHA384 or algorithm == HMAC_SHA512):
-        raise NotImplementedError("TSIG algorithm " + str(algorithm) +
-                                  " requires Python 2.5.2 or later")
-
     try:
-        return (algorithm.to_digestable(), _hashes[algorithm])
+        return (algorithm.to_digestable(), dns.hash.hashes[algorithm])
     except KeyError:
         raise NotImplementedError("TSIG algorithm " + str(algorithm) +
                                   " is not supported")
 
+
 def get_algorithm_and_mac(wire, tsig_rdata, tsig_rdlen):
     """Return the tsig algorithm for the specified tsig_rdata
     @raises FormError: The TSIG is badly formed.
@@ -230,7 +209,7 @@ def get_algorithm_and_mac(wire, tsig_rda
     (aname, used) = dns.name.from_wire(wire, current)
     current = current + used
     (upper_time, lower_time, fudge, mac_size) = \
-                 struct.unpack("!HIHH", wire[current:current + 10])
+        struct.unpack("!HIHH", wire[current:current + 10])
     current += 10
     mac = wire[current:current + mac_size]
     current += mac_size
Index: dnspython-1.12.0/dns/tsigkeyring.py
===================================================================
--- dnspython-1.12.0.orig/dns/tsigkeyring.py
+++ dnspython-1.12.0/dns/tsigkeyring.py
@@ -19,11 +19,12 @@ import base64
 
 import dns.name
 
+
 def from_text(textring):
     """Convert a dictionary containing (textual DNS name, base64 secret) pairs
     into a binary keyring which has (dns.name.Name, binary secret) pairs.
     @rtype: dict"""
-    
+
     keyring = {}
     for keytext in textring:
         keyname = dns.name.from_text(keytext)
@@ -31,11 +32,12 @@ def from_text(textring):
         keyring[keyname] = secret
     return keyring
 
+
 def to_text(keyring):
     """Convert a dictionary containing (dns.name.Name, binary secret) pairs
     into a text keyring which has (textual DNS name, base64 secret) pairs.
     @rtype: dict"""
-    
+
     textring = {}
     for keyname in keyring:
         keytext = keyname.to_text()
Index: dnspython-1.12.0/dns/ttl.py
===================================================================
--- dnspython-1.12.0.orig/dns/ttl.py
+++ dnspython-1.12.0/dns/ttl.py
@@ -16,6 +16,7 @@
 """DNS TTL conversion."""
 
 import dns.exception
+from ._compat import long
 
 class BadTTL(dns.exception.SyntaxError):
     pass
@@ -36,8 +37,8 @@ def from_text(text):
     else:
         if not text[0].isdigit():
             raise BadTTL
-        total = 0L
-        current = 0L
+        total = long(0)
+        current = long(0)
         for c in text:
             if c.isdigit():
                 current *= 10
@@ -45,13 +46,13 @@ def from_text(text):
             else:
                 c = c.lower()
                 if c == 'w':
-                    total += current * 604800L
+                    total += current * long(604800)
                 elif c == 'd':
-                    total += current * 86400L
+                    total += current * long(86400)
                 elif c == 'h':
-                    total += current * 3600L
+                    total += current * long(3600)
                 elif c == 'm':
-                    total += current * 60L
+                    total += current * long(60)
                 elif c == 's':
                     total += current
                 else:
@@ -59,6 +60,6 @@ def from_text(text):
                 current = 0
         if not current == 0:
             raise BadTTL("trailing integer")
-    if total < 0L or total > 2147483647L:
+    if total < long(0) or total > long(2147483647):
         raise BadTTL("TTL should be between 0 and 2^31 - 1 (inclusive)")
     return total
Index: dnspython-1.12.0/dns/update.py
===================================================================
--- dnspython-1.12.0.orig/dns/update.py
+++ dnspython-1.12.0/dns/update.py
@@ -15,6 +15,7 @@
 
 """DNS Dynamic Update Support"""
 
+
 import dns.message
 import dns.name
 import dns.opcode
@@ -22,8 +23,11 @@ import dns.rdata
 import dns.rdataclass
 import dns.rdataset
 import dns.tsig
+from ._compat import string_types
+
 
 class Update(dns.message.Message):
+
     def __init__(self, zone, rdclass=dns.rdataclass.IN, keyring=None,
                  keyname=None, keyalgorithm=dns.tsig.default_algorithm):
         """Initialize a new DNS Update object.
@@ -51,7 +55,7 @@ class Update(dns.message.Message):
         """
         super(Update, self).__init__()
         self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE)
-        if isinstance(zone, (str, unicode)):
+        if isinstance(zone, string_types):
             zone = dns.name.from_text(zone)
         self.origin = zone
         if isinstance(rdclass, str):
@@ -85,7 +89,7 @@ class Update(dns.message.Message):
 
                 - ttl, rdtype, string..."""
 
-        if isinstance(name, (str, unicode)):
+        if isinstance(name, string_types):
             name = dns.name.from_text(name, None)
         if isinstance(args[0], dns.rdataset.Rdataset):
             for rds in args:
@@ -135,7 +139,7 @@ class Update(dns.message.Message):
 
                 - rdtype, [string...]"""
 
-        if isinstance(name, (str, unicode)):
+        if isinstance(name, string_types):
             name = dns.name.from_text(name, None)
         if len(args) == 0:
             rrset = self.find_rrset(self.authority, name, dns.rdataclass.ANY,
@@ -152,7 +156,7 @@ class Update(dns.message.Message):
                     self._add_rr(name, 0, rd, dns.rdataclass.NONE)
             else:
                 rdtype = args.pop(0)
-                if isinstance(rdtype, (str, unicode)):
+                if isinstance(rdtype, string_types):
                     rdtype = dns.rdatatype.from_text(rdtype)
                 if len(args) == 0:
                     rrset = self.find_rrset(self.authority, name,
@@ -193,16 +197,16 @@ class Update(dns.message.Message):
 
                 - rdtype, string..."""
 
-        if isinstance(name, (str, unicode)):
+        if isinstance(name, string_types):
             name = dns.name.from_text(name, None)
         if len(args) == 0:
-            rrset = self.find_rrset(self.answer, name,
-                                    dns.rdataclass.ANY, dns.rdatatype.ANY,
-                                    dns.rdatatype.NONE, None,
-                                    True, True)
+            self.find_rrset(self.answer, name,
+                            dns.rdataclass.ANY, dns.rdatatype.ANY,
+                            dns.rdatatype.NONE, None,
+                            True, True)
         elif isinstance(args[0], dns.rdataset.Rdataset) or \
-             isinstance(args[0], dns.rdata.Rdata) or \
-             len(args) > 1:
+            isinstance(args[0], dns.rdata.Rdata) or \
+                len(args) > 1:
             if not isinstance(args[0], dns.rdataset.Rdataset):
                 # Add a 0 TTL
                 args = list(args)
@@ -210,31 +214,31 @@ class Update(dns.message.Message):
             self._add(False, self.answer, name, *args)
         else:
             rdtype = args[0]
-            if isinstance(rdtype, (str, unicode)):
+            if isinstance(rdtype, string_types):
                 rdtype = dns.rdatatype.from_text(rdtype)
-            rrset = self.find_rrset(self.answer, name,
-                                    dns.rdataclass.ANY, rdtype,
-                                    dns.rdatatype.NONE, None,
-                                    True, True)
+            self.find_rrset(self.answer, name,
+                            dns.rdataclass.ANY, rdtype,
+                            dns.rdatatype.NONE, None,
+                            True, True)
 
     def absent(self, name, rdtype=None):
         """Require that an owner name (and optionally an rdata type) does
         not exist as a prerequisite to the execution of the update."""
 
-        if isinstance(name, (str, unicode)):
+        if isinstance(name, string_types):
             name = dns.name.from_text(name, None)
         if rdtype is None:
-            rrset = self.find_rrset(self.answer, name,
-                                    dns.rdataclass.NONE, dns.rdatatype.ANY,
-                                    dns.rdatatype.NONE, None,
-                                    True, True)
+            self.find_rrset(self.answer, name,
+                            dns.rdataclass.NONE, dns.rdatatype.ANY,
+                            dns.rdatatype.NONE, None,
+                            True, True)
         else:
-            if isinstance(rdtype, (str, unicode)):
+            if isinstance(rdtype, string_types):
                 rdtype = dns.rdatatype.from_text(rdtype)
-            rrset = self.find_rrset(self.answer, name,
-                                    dns.rdataclass.NONE, rdtype,
-                                    dns.rdatatype.NONE, None,
-                                    True, True)
+            self.find_rrset(self.answer, name,
+                            dns.rdataclass.NONE, rdtype,
+                            dns.rdatatype.NONE, None,
+                            True, True)
 
     def to_wire(self, origin=None, max_size=65535):
         """Return a string containing the update in DNS compressed wire
Index: dnspython-1.12.0/dns/version.py
===================================================================
--- dnspython-1.12.0.orig/dns/version.py
+++ dnspython-1.12.0/dns/version.py
@@ -31,4 +31,4 @@ else:
               (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL)
 
 hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \
-             SERIAL
+    SERIAL
Index: dnspython-1.12.0/dns/wiredata.py
===================================================================
--- dnspython-1.12.0.orig/dns/wiredata.py
+++ dnspython-1.12.0/dns/wiredata.py
@@ -15,9 +15,9 @@
 
 """DNS Wire Data Helper"""
 
-import sys
 
 import dns.exception
+from ._compat import binary_type, string_types
 
 # Figure out what constant python passes for an unspecified slice bound.
 # It's supposed to be sys.maxint, yet on 64-bit windows sys.maxint is 2^31 - 1
@@ -25,19 +25,26 @@ import dns.exception
 # extra comparisons, duplicating code, or weakening WireData, we just figure
 # out what constant Python will use.
 
+
 class _SliceUnspecifiedBound(str):
+
     def __getslice__(self, i, j):
         return j
 
 _unspecified_bound = _SliceUnspecifiedBound('')[1:]
 
-class WireData(str):
+
+class WireData(binary_type):
     # WireData is a string with stricter slicing
+
     def __getitem__(self, key):
         try:
-            return WireData(super(WireData, self).__getitem__(key))
+            if isinstance(key, slice):
+                return WireData(super(WireData, self).__getitem__(key))
+            return bytearray(self.unwrap())[key]
         except IndexError:
             raise dns.exception.FormError
+
     def __getslice__(self, i, j):
         try:
             if j == _unspecified_bound:
@@ -53,6 +60,7 @@ class WireData(str):
             return WireData(super(WireData, self).__getslice__(i, j))
         except IndexError:
             raise dns.exception.FormError
+
     def __iter__(self):
         i = 0
         while 1:
@@ -61,11 +69,16 @@ class WireData(str):
                 i += 1
             except dns.exception.FormError:
                 raise StopIteration
+
     def unwrap(self):
-        return str(self)
+        return binary_type(self)
+
 
 def maybe_wrap(wire):
-    if not isinstance(wire, WireData):
-        return WireData(wire)
-    else:
+    if isinstance(wire, WireData):
         return wire
+    elif isinstance(wire, binary_type):
+        return WireData(wire)
+    elif isinstance(wire, string_types):
+        return WireData(wire.encode())
+    raise ValueError("unhandled type %s" % type(wire))
Index: dnspython-1.12.0/dns/zone.py
===================================================================
--- dnspython-1.12.0.orig/dns/zone.py
+++ dnspython-1.12.0/dns/zone.py
@@ -19,6 +19,7 @@ from __future__ import generators
 
 import sys
 import re
+from io import BytesIO
 
 import dns.exception
 import dns.name
@@ -30,6 +31,7 @@ import dns.rrset
 import dns.tokenizer
 import dns.ttl
 import dns.grange
+from ._compat import xrange, string_types, text_type, binary_type
 
 try:
     from cStringIO import StringIO
@@ -114,13 +116,14 @@ class Zone(object):
         return not self.__eq__(other)
 
     def _validate_name(self, name):
-        if isinstance(name, (str, unicode)):
+        if isinstance(name, string_types):
             name = dns.name.from_text(name, None)
         elif not isinstance(name, dns.name.Name):
             raise KeyError("name parameter must be convertable to a DNS name")
         if name.is_absolute():
             if not name.is_subdomain(self.origin):
-                raise KeyError("name parameter must be a subdomain of the zone origin")
+                raise KeyError(
+                    "name parameter must be a subdomain of the zone origin")
             if self.relativize:
                 name = name.relativize(self.origin)
         return name
@@ -152,12 +155,11 @@ class Zone(object):
     def values(self):
         return self.nodes.values()
 
-    def iteritems(self):
-        return self.nodes.iteritems()
-
     def items(self):
         return self.nodes.items()
 
+    iteritems = items
+
     def get(self, key):
         key = self._validate_name(key)
         return self.nodes.get(key)
@@ -212,7 +214,7 @@ class Zone(object):
         """
 
         name = self._validate_name(name)
-        if self.nodes.has_key(name):
+        if name in self.nodes:
             del self.nodes[name]
 
     def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE,
@@ -244,9 +246,9 @@ class Zone(object):
         """
 
         name = self._validate_name(name)
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
-        if isinstance(covers, (str, unicode)):
+        if isinstance(covers, string_types):
             covers = dns.rdatatype.from_text(covers)
         node = self.find_node(name, create)
         return node.find_rdataset(self.rdclass, rdtype, covers, create)
@@ -307,12 +309,12 @@ class Zone(object):
         """
 
         name = self._validate_name(name)
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
-        if isinstance(covers, (str, unicode)):
+        if isinstance(covers, string_types):
             covers = dns.rdatatype.from_text(covers)
         node = self.get_node(name)
-        if not node is None:
+        if node is not None:
             node.delete_rdataset(self.rdclass, rdtype, covers)
             if len(node) == 0:
                 self.delete_node(name)
@@ -370,9 +372,9 @@ class Zone(object):
         """
 
         name = self._validate_name(name)
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
-        if isinstance(covers, (str, unicode)):
+        if isinstance(covers, string_types):
             covers = dns.rdatatype.from_text(covers)
         rdataset = self.nodes[name].find_rdataset(self.rdclass, rdtype, covers)
         rrset = dns.rrset.RRset(name, self.rdclass, rdtype, covers)
@@ -426,9 +428,9 @@ class Zone(object):
         @type covers: int or string
         """
 
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
-        if isinstance(covers, (str, unicode)):
+        if isinstance(covers, string_types):
             covers = dns.rdatatype.from_text(covers)
         for (name, node) in self.iteritems():
             for rds in node:
@@ -449,9 +451,9 @@ class Zone(object):
         @type covers: int or string
         """
 
-        if isinstance(rdtype, (str, unicode)):
+        if isinstance(rdtype, string_types):
             rdtype = dns.rdatatype.from_text(rdtype)
-        if isinstance(covers, (str, unicode)):
+        if isinstance(covers, string_types):
             covers = dns.rdatatype.from_text(covers)
         for (name, node) in self.iteritems():
             for rds in node:
@@ -478,31 +480,32 @@ class Zone(object):
         @type nl: string or None
         """
 
-        if sys.hexversion >= 0x02030000:
-            # allow Unicode filenames
-            str_type = basestring
-        else:
-            str_type = str
+        str_type = string_types
+
         if nl is None:
-            opts = 'w'
+            opts = 'wb'
         else:
             opts = 'wb'
+
         if isinstance(f, str_type):
-            f = file(f, opts)
+            f = open(f, opts)
             want_close = True
         else:
             want_close = False
         try:
             if sorted:
-                names = self.keys()
+                names = list(self.keys())
                 names.sort()
             else:
                 names = self.iterkeys()
             for n in names:
                 l = self[n].to_text(n, origin=self.origin,
                                     relativize=relativize)
+                if isinstance(l, text_type):
+                    l = l.encode()
                 if nl is None:
-                    print >> f, l
+                    f.write(l)
+                    f.write('\n')
                 else:
                     f.write(l)
                     f.write(nl)
@@ -525,7 +528,7 @@ class Zone(object):
         LF on POSIX, CRLF on Windows, CR on Macintosh).
         @type nl: string or None
         """
-        temp_buffer = StringIO()
+        temp_buffer = BytesIO()
         self.to_file(temp_buffer, sorted, relativize, nl)
         return_value = temp_buffer.getvalue()
         temp_buffer.close()
@@ -549,6 +552,7 @@ class Zone(object):
 
 
 class _MasterReader(object):
+
     """Read a DNS master file
 
     @ivar tok: The tokenizer
@@ -577,7 +581,7 @@ class _MasterReader(object):
 
     def __init__(self, tok, origin, rdclass, relativize, zone_factory=Zone,
                  allow_include=False, check_origin=True):
-        if isinstance(origin, (str, unicode)):
+        if isinstance(origin, string_types):
             origin = dns.name.from_text(origin)
         self.tok = tok
         self.current_origin = origin
@@ -601,9 +605,10 @@ class _MasterReader(object):
         # Name
         if self.current_origin is None:
             raise UnknownOrigin
-        token = self.tok.get(want_leading = True)
+        token = self.tok.get(want_leading=True)
         if not token.is_whitespace():
-            self.last_name = dns.name.from_text(token.value, self.current_origin)
+            self.last_name = dns.name.from_text(
+                token.value, self.current_origin)
         else:
             token = self.tok.get()
             if token.is_eol_or_eof():
@@ -643,7 +648,8 @@ class _MasterReader(object):
         try:
             rdtype = dns.rdatatype.from_text(token.value)
         except:
-            raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
+            raise dns.exception.SyntaxError(
+                "unknown rdatatype '%s'" % token.value)
         n = self.zone.nodes.get(name)
         if n is None:
             n = self.zone.node_factory()
@@ -662,7 +668,8 @@ class _MasterReader(object):
             # We convert them to syntax errors so that we can emit
             # helpful filename:line info.
             (ty, va) = sys.exc_info()[:2]
-            raise dns.exception.SyntaxError("caught exception %s: %s" % (str(ty), str(va)))
+            raise dns.exception.SyntaxError(
+                "caught exception %s: %s" % (str(ty), str(va)))
 
         rd.choose_relativity(self.zone.origin, self.relativize)
         covers = rd.covers()
@@ -764,7 +771,7 @@ class _MasterReader(object):
                 raise dns.exception.SyntaxError
         except:
             raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
-                    token.value)
+                                            token.value)
 
         # lhs (required)
         try:
@@ -772,28 +779,26 @@ class _MasterReader(object):
         except:
             raise dns.exception.SyntaxError
 
-
         lmod, lsign, loffset, lwidth, lbase = self._parse_modify(lhs)
         rmod, rsign, roffset, rwidth, rbase = self._parse_modify(rhs)
         for i in range(start, stop + 1, step):
             # +1 because bind is inclusive and python is exclusive
 
-            if lsign == '+':
+            if lsign == u'+':
                 lindex = i + int(loffset)
-            elif lsign == '-':
+            elif lsign == u'-':
                 lindex = i - int(loffset)
 
-            if rsign == '-':
+            if rsign == u'-':
                 rindex = i - int(roffset)
-            elif rsign == '+':
+            elif rsign == u'+':
                 rindex = i + int(roffset)
 
             lzfindex = str(lindex).zfill(int(lwidth))
             rzfindex = str(rindex).zfill(int(rwidth))
 
-
-            name = lhs.replace('$%s' % (lmod), lzfindex)
-            rdata = rhs.replace('$%s' % (rmod), rzfindex)
+            name = lhs.replace(u'$%s' % (lmod), lzfindex)
+            rdata = rhs.replace(u'$%s' % (rmod), rzfindex)
 
             self.last_name = dns.name.from_text(name, self.current_origin)
             name = self.last_name
@@ -822,7 +827,7 @@ class _MasterReader(object):
                 # helpful filename:line info.
                 (ty, va) = sys.exc_info()[:2]
                 raise dns.exception.SyntaxError("caught exception %s: %s" %
-                        (str(ty), str(va)))
+                                                (str(ty), str(va)))
 
             rd.choose_relativity(self.zone.origin, self.relativize)
             covers = rd.covers()
@@ -840,7 +845,7 @@ class _MasterReader(object):
             while 1:
                 token = self.tok.get(True, True)
                 if token.is_eof():
-                    if not self.current_file is None:
+                    if self.current_file is not None:
                         self.current_file.close()
                     if len(self.saved_state) > 0:
                         (self.tok,
@@ -855,29 +860,31 @@ class _MasterReader(object):
                 elif token.is_comment():
                     self.tok.get_eol()
                     continue
-                elif token.value[0] == '$':
-                    u = token.value.upper()
-                    if u == '$TTL':
+                elif token.value[0] == u'$':
+                    c = token.value.upper()
+                    if c == u'$TTL':
                         token = self.tok.get()
                         if not token.is_identifier():
                             raise dns.exception.SyntaxError("bad $TTL")
                         self.ttl = dns.ttl.from_text(token.value)
                         self.tok.get_eol()
-                    elif u == '$ORIGIN':
+                    elif c == u'$ORIGIN':
                         self.current_origin = self.tok.get_name()
                         self.tok.get_eol()
                         if self.zone.origin is None:
                             self.zone.origin = self.current_origin
-                    elif u == '$INCLUDE' and self.allow_include:
+                    elif c == u'$INCLUDE' and self.allow_include:
                         token = self.tok.get()
                         filename = token.value
                         token = self.tok.get()
                         if token.is_identifier():
-                            new_origin = dns.name.from_text(token.value, \
-                                                            self.current_origin)
+                            new_origin =\
+                                dns.name.from_text(token.value,
+                                                   self.current_origin)
                             self.tok.get_eol()
                         elif not token.is_eol_or_eof():
-                            raise dns.exception.SyntaxError("bad origin in $INCLUDE")
+                            raise dns.exception.SyntaxError(
+                                "bad origin in $INCLUDE")
                         else:
                             new_origin = self.current_origin
                         self.saved_state.append((self.tok,
@@ -885,29 +892,32 @@ class _MasterReader(object):
                                                  self.last_name,
                                                  self.current_file,
                                                  self.ttl))
-                        self.current_file = file(filename, 'r')
+                        self.current_file = open(filename, 'r')
                         self.tok = dns.tokenizer.Tokenizer(self.current_file,
                                                            filename)
                         self.current_origin = new_origin
-                    elif u == '$GENERATE':
+                    elif c == u'$GENERATE':
                         self._generate_line()
                     else:
-                        raise dns.exception.SyntaxError("Unknown master file directive '" + u + "'")
+                        raise dns.exception.SyntaxError(
+                            "Unknown master file directive '" + c + "'")
                     continue
                 self.tok.unget(token)
                 self._rr_line()
-        except dns.exception.SyntaxError, detail:
+        except dns.exception.SyntaxError as detail:
             (filename, line_number) = self.tok.where()
             if detail is None:
                 detail = "syntax error"
-            raise dns.exception.SyntaxError("%s:%d: %s" % (filename, line_number, detail))
+            raise dns.exception.SyntaxError(
+                "%s:%d: %s" % (filename, line_number, detail))
 
         # Now that we're done reading, do some basic checking of the zone.
         if self.check_origin:
             self.zone.check_origin()
 
-def from_text(text, origin = None, rdclass = dns.rdataclass.IN,
-              relativize = True, zone_factory=Zone, filename=None,
+
+def from_text(text, origin=None, rdclass=dns.rdataclass.IN,
+              relativize=True, zone_factory=Zone, filename=None,
               allow_include=False, check_origin=True):
     """Build a zone object from a master file format string.
 
@@ -949,8 +959,9 @@ def from_text(text, origin = None, rdcla
     reader.read()
     return reader.zone
 
-def from_file(f, origin = None, rdclass = dns.rdataclass.IN,
-              relativize = True, zone_factory=Zone, filename=None,
+
+def from_file(f, origin=None, rdclass=dns.rdataclass.IN,
+              relativize=True, zone_factory=Zone, filename=None,
               allow_include=True, check_origin=True):
     """Read a master file and build a zone object.
 
@@ -980,17 +991,13 @@ def from_file(f, origin = None, rdclass
     @rtype: dns.zone.Zone object
     """
 
-    if sys.hexversion >= 0x02030000:
-        # allow Unicode filenames; turn on universal newline support
-        str_type = basestring
-        opts = 'rU'
-    else:
-        str_type = str
-        opts = 'r'
+    str_type = string_types
+    opts = 'rU'
+
     if isinstance(f, str_type):
         if filename is None:
             filename = f
-        f = file(f, opts)
+        f = open(f, opts)
         want_close = True
     else:
         if filename is None:
@@ -1005,6 +1012,7 @@ def from_file(f, origin = None, rdclass
             f.close()
     return z
 
+
 def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True):
     """Convert the output of a zone transfer generator into a zone object.
 
Index: dnspython-1.12.0/tests/test_bugs.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_bugs.py
+++ dnspython-1.12.0/tests/test_bugs.py
@@ -24,15 +24,15 @@ class BugsTestCase(unittest.TestCase):
 
     def test_float_LOC(self):
         rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC,
-                                    "30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m")
+                                    u"30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m")
         self.failUnless(rdata.float_latitude == 30.5)
         self.failUnless(rdata.float_longitude == -100.5)
 
     def test_SOA_BIND8_TTL(self):
         rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
-                                     "a b 100 1s 1m 1h 1d")
+                                     u"a b 100 1s 1m 1h 1d")
         rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
-                                     "a b 100 1 60 3600 86400")
+                                     u"a b 100 1 60 3600 86400")
         self.failUnless(rdata1 == rdata2)
 
     def test_TTL_bounds_check(self):
@@ -42,7 +42,7 @@ class BugsTestCase(unittest.TestCase):
 
     def test_empty_NSEC3_window(self):
         rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3,
-                                    "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715")
+                                    u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715")
         self.failUnless(rdata.windows == [])
 
     def test_zero_size_APL(self):
Index: dnspython-1.12.0/tests/test_dnssec.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_dnssec.py
+++ dnspython-1.12.0/tests/test_dnssec.py
@@ -230,4 +230,4 @@ if __name__ == '__main__':
     if import_ok:
         unittest.main()
     else:
-        print 'skipping DNSSEC tests because pycrypto is not installed'
+        print('skipping DNSSEC tests because pycrypto is not installed')
Index: dnspython-1.12.0/tests/test_generate.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_generate.py
+++ dnspython-1.12.0/tests/test_generate.py
@@ -16,7 +16,6 @@
 import sys
 sys.path.insert(0, '../')  # Force the local project to be *the* dns
 
-import cStringIO
 import filecmp
 import os
 import unittest
@@ -27,9 +26,11 @@ import dns.rdataclass
 import dns.rdatatype
 import dns.rrset
 import dns.zone
+from dns._compat import long
 
 import pprint
 
+
 pp = pprint.PrettyPrinter(indent=2)
 
 import pdb
@@ -133,6 +134,9 @@ ns2 3600 IN A 10.0.0.2
 $GENERATE 27-28 $.2 PTR zlb${-26}.oob
 """
 
+def _rdata_sort(a):
+    return (a[0], a[2].rdclass, a[2].to_text())
+
 
 class GenerateTestCase(unittest.TestCase):
 
@@ -149,7 +153,7 @@ class GenerateTestCase(unittest.TestCase
     def testIterateAllRdatas2(self):
         z = dns.zone.from_text(example_text2, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
                 3600,
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
@@ -187,13 +191,13 @@ class GenerateTestCase(unittest.TestCase
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.5'))]
 
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testIterateAllRdatas3(self):
         z = dns.zone.from_text(example_text3, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
                 3600,
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
@@ -227,271 +231,271 @@ class GenerateTestCase(unittest.TestCase
                 (dns.name.from_text('foo8', None), 3600,
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.8'))]
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
     def testGenerate1(self):
         z = dns.zone.from_text(example_text4, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
 
                 (dns.name.from_text('wp-db01.services.mozilla.com', None),
-                    0L,
+                    long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
                 (dns.name.from_text('wp-db02.services.mozilla.com', None),
-                    0L,
+                    long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
                 (dns.name.from_text('wp-db03.services.mozilla.com', None),
-                    0L,
+                    long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.'))]
-        exl.sort()
-        self.failUnless(l == exl)
+        exl.sort(key=_rdata_sort)
+        self.assertEqual(l, exl)
 
     def testGenerate2(self):
         z = dns.zone.from_text(example_text5, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
 
-                (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db21.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
-                (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db22.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
-                (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db23.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.'))]
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testGenerate3(self):
         z = dns.zone.from_text(example_text6, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
 
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
-                (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db21.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
-                (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db22.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.')),
 
-                (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L,
+                (dns.name.from_text('wp-db23.services.mozilla.com', None), long(0),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
                                     'SERVER.FOOBAR.'))]
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testGenerate4(self):
         z = dns.zone.from_text(example_text7, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
 
-                (dns.name.from_text('sync1.db', None), 3600L,
+                (dns.name.from_text('sync1.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
 
-                (dns.name.from_text('sync2.db', None), 3600L,
+                (dns.name.from_text('sync2.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
 
-                (dns.name.from_text('sync3.db', None), 3600L,
+                (dns.name.from_text('sync3.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0'))]
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testGenerate6(self):
         z = dns.zone.from_text(example_text9, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
 
-                (dns.name.from_text('wp-db01', None), 3600L,
+                (dns.name.from_text('wp-db01', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
-                (dns.name.from_text('wp-db02', None), 3600L,
+                (dns.name.from_text('wp-db02', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
 
-                (dns.name.from_text('sync1.db', None), 3600L,
+                (dns.name.from_text('sync1.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
 
-                (dns.name.from_text('sync2.db', None), 3600L,
+                (dns.name.from_text('sync2.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0')),
 
-                (dns.name.from_text('sync3.db', None), 3600L,
+                (dns.name.from_text('sync3.db', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.10.16.0'))]
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testGenerate7(self):
         z = dns.zone.from_text(example_text10, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns1')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
                                     'ns2')),
                (dns.name.from_text('@', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
                                     'foo bar 1 2 3 4 5')),
                (dns.name.from_text('bar.foo', None),
-                300L,
+                long(300),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
                                     '0 blaz.foo')),
                (dns.name.from_text('ns1', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.1')),
                (dns.name.from_text('ns2', None),
-                3600L,
+                long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2')),
 
-                (dns.name.from_text('27.2', None), 3600L,
+                (dns.name.from_text('27.2', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
                                     'zlb1.oob')),
 
-                (dns.name.from_text('28.2', None), 3600L,
+                (dns.name.from_text('28.2', None), long(3600),
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
                                     'zlb2.oob'))]
 
-        exl.sort()
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
 
Index: dnspython-1.12.0/tests/test_grange.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_grange.py
+++ dnspython-1.12.0/tests/test_grange.py
@@ -16,7 +16,6 @@
 import sys
 sys.path.insert(0, '../')
 
-import cStringIO
 import filecmp
 import os
 import unittest
Index: dnspython-1.12.0/tests/test_message.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_message.py
+++ dnspython-1.12.0/tests/test_message.py
@@ -13,13 +13,15 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
 import os
 import unittest
+import binascii
 
 import dns.exception
 import dns.message
 
+from dns._compat import xrange
+
 query_text = """id 1234
 opcode QUERY
 rcode NOERROR
@@ -33,10 +35,10 @@ wwww.dnspython.org. IN A
 ;AUTHORITY
 ;ADDITIONAL"""
 
-goodhex = '04d201000001000000000001047777777709646e73707974686f6e' \
-          '036f726700000100010000291000000080000000'
+goodhex = b'04d201000001000000000001047777777709646e73707974686f6e' \
+          b'036f726700000100010000291000000080000000'
 
-goodwire = goodhex.decode('hex_codec')
+goodwire = binascii.unhexlify(goodhex)
 
 answer_text = """id 1234
 opcode QUERY
@@ -66,7 +68,7 @@ goodhex2 = '04d2 8500 0001 0001 0003 000
            'c091 0001 0001 00000e10 0004 cc98ba96'
 
 
-goodwire2 = goodhex2.replace(' ', '').decode('hex_codec')
+goodwire2 = binascii.unhexlify(goodhex2.replace(' ', '').encode())
 
 query_text_2 = """id 1234
 opcode QUERY
@@ -81,10 +83,10 @@ wwww.dnspython.org. IN A
 ;AUTHORITY
 ;ADDITIONAL"""
 
-goodhex3 = '04d2010f0001000000000001047777777709646e73707974686f6e' \
-          '036f726700000100010000291000ff0080000000'
+goodhex3 = b'04d2010f0001000000000001047777777709646e73707974686f6e' \
+           b'036f726700000100010000291000ff0080000000'
 
-goodwire3 = goodhex3.decode('hex_codec')
+goodwire3 = binascii.unhexlify(goodhex3)
 
 class MessageTestCase(unittest.TestCase):
 
@@ -116,7 +118,7 @@ class MessageTestCase(unittest.TestCase)
 
     def test_EDNS_from_wire1(self):
         m = dns.message.from_wire(goodwire)
-        self.failUnless(str(m) == query_text)
+        self.assertEqual(str(m), query_text)
 
     def test_EDNS_to_wire2(self):
         q = dns.message.from_text(query_text_2)
@@ -146,13 +148,13 @@ class MessageTestCase(unittest.TestCase)
 
     def test_TrailingJunk(self):
         def bad():
-            badwire = goodwire + '\x00'
+            badwire = goodwire + b'\x00'
             m = dns.message.from_wire(badwire)
         self.failUnlessRaises(dns.message.TrailingJunk, bad)
 
     def test_ShortHeader(self):
         def bad():
-            badwire = '\x00' * 11
+            badwire = b'\x00' * 11
             m = dns.message.from_wire(badwire)
         self.failUnlessRaises(dns.message.ShortHeader, bad)
 
Index: dnspython-1.12.0/tests/test_name.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_name.py
+++ dnspython-1.12.0/tests/test_name.py
@@ -15,7 +15,7 @@
 
 import unittest
 
-import cStringIO
+from io import BytesIO
 import socket
 
 import dns.name
@@ -28,15 +28,15 @@ class NameTestCase(unittest.TestCase):
 
     def testFromTextRel1(self):
         n = dns.name.from_text('foo.bar')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b''))
 
     def testFromTextRel2(self):
         n = dns.name.from_text('foo.bar', origin=self.origin)
-        self.failUnless(n.labels == ('foo', 'bar', 'example', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b'example', b''))
 
     def testFromTextRel3(self):
         n = dns.name.from_text('foo.bar', origin=None)
-        self.failUnless(n.labels == ('foo', 'bar'))
+        self.assertEqual(n.labels, (b'foo', b'bar'))
 
     def testFromTextRel4(self):
         n = dns.name.from_text('@', origin=None)
@@ -48,33 +48,33 @@ class NameTestCase(unittest.TestCase):
 
     def testFromTextAbs1(self):
         n = dns.name.from_text('foo.bar.')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels,(b'foo', b'bar', b''))
 
     def testTortureFromText(self):
         good = [
-            r'.',
-            r'a',
-            r'a.',
-            r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
-            r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
-            r'\000.\008.\010.\032.\046.\092.\099.\255',
-            r'\\',
-            r'\..\.',
-            r'\\.\\',
-            r'!"#%&/()=+-',
-            r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
+            br'.',
+            br'a',
+            br'a.',
+            br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+            br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+            br'\000.\008.\010.\032.\046.\092.\099.\255',
+            br'\\',
+            br'\..\.',
+            br'\\.\\',
+            br'!"#%&/()=+-',
+            br'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
             ]
         bad = [
-            r'..',
-            r'.a',
-            r'\\..',
-            '\\',		# yes, we don't want the 'r' prefix!
-            r'\0',
-            r'\00',
-            r'\00Z',
-            r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
-            r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
-            r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
+            br'..',
+            br'.a',
+            br'\\..',
+            b'\\',		# yes, we don't want the 'r' prefix!
+            br'\0',
+            br'\00',
+            br'\00Z',
+            br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+            br'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+            br'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
             ]
         for t in good:
             try:
@@ -134,7 +134,7 @@ class NameTestCase(unittest.TestCase):
     def testHash1(self):
         n1 = dns.name.from_text('fOo.COM')
         n2 = dns.name.from_text('foo.com')
-        self.failUnless(hash(n1) == hash(n2))
+        self.assertEqual(hash(n1), hash(n2))
 
     def testCompare1(self):
         n1 = dns.name.from_text('a')
@@ -155,9 +155,6 @@ class NameTestCase(unittest.TestCase):
     def testCompare4(self):
         self.failUnless(dns.name.root != 1)
 
-    def testCompare5(self):
-        self.failUnless(dns.name.root < 1 or dns.name.root > 1)
-
     def testSubdomain1(self):
         self.failUnless(not dns.name.empty.is_subdomain(dns.name.root))
 
@@ -197,60 +194,60 @@ class NameTestCase(unittest.TestCase):
     def testCanonicalize1(self):
         n = dns.name.from_text('FOO.bar', origin=self.origin)
         c = n.canonicalize()
-        self.failUnless(c.labels == ('foo', 'bar', 'example', ''))
+        self.assertEqual(c.labels, (b'foo', b'bar', b'example', b''))
 
     def testToText1(self):
         n = dns.name.from_text('FOO.bar', origin=self.origin)
         t = n.to_text()
-        self.failUnless(t == 'FOO.bar.example.')
+        self.assertEqual(t, b'FOO.bar.example.')
 
     def testToText2(self):
         n = dns.name.from_text('FOO.bar', origin=self.origin)
         t = n.to_text(True)
-        self.failUnless(t == 'FOO.bar.example')
+        self.assertEqual(t, b'FOO.bar.example')
 
     def testToText3(self):
         n = dns.name.from_text('FOO.bar', origin=None)
         t = n.to_text()
-        self.failUnless(t == 'FOO.bar')
+        self.assertEqual(t, b'FOO.bar')
 
     def testToText4(self):
         t = dns.name.empty.to_text()
-        self.failUnless(t == '@')
+        self.assertEqual(t, b'@')
 
     def testToText5(self):
         t = dns.name.root.to_text()
-        self.failUnless(t == '.')
+        self.assertEqual(t, b'.')
 
     def testToText6(self):
         n = dns.name.from_text('FOO bar', origin=None)
         t = n.to_text()
-        self.failUnless(t == r'FOO\032bar')
+        self.assertEqual(t, br'FOO\032bar')
 
     def testToText7(self):
         n = dns.name.from_text(r'FOO\.bar', origin=None)
         t = n.to_text()
-        self.failUnless(t == r'FOO\.bar')
+        self.assertEqual(t, b'FOO\.bar')
 
     def testToText8(self):
         n = dns.name.from_text(r'\070OO\.bar', origin=None)
         t = n.to_text()
-        self.failUnless(t == r'FOO\.bar')
+        self.assertEqual(t, b'FOO\.bar')
 
     def testSlice1(self):
         n = dns.name.from_text(r'a.b.c.', origin=None)
         s = n[:]
-        self.failUnless(s == ('a', 'b', 'c', ''))
+        self.assertEqual(s, (b'a', b'b', b'c', b''))
 
     def testSlice2(self):
         n = dns.name.from_text(r'a.b.c.', origin=None)
         s = n[:2]
-        self.failUnless(s == ('a', 'b'))
+        self.assertEqual(s, (b'a', b'b'))
 
     def testSlice3(self):
         n = dns.name.from_text(r'a.b.c.', origin=None)
         s = n[2:]
-        self.failUnless(s == ('c', ''))
+        self.assertEqual(s, (b'c', b''))
 
     def testEmptyLabel1(self):
         def bad():
@@ -329,13 +326,13 @@ class NameTestCase(unittest.TestCase):
     def testBadEscape(self):
         def bad():
             n = dns.name.from_text(r'a.b\0q1.c.')
-            print n
+            print(n)
         self.failUnlessRaises(dns.name.BadEscape, bad)
 
     def testDigestable1(self):
         n = dns.name.from_text('FOO.bar')
         d = n.to_digestable()
-        self.failUnless(d == '\x03foo\x03bar\x00')
+        self.assertEqual(d, b'\x03foo\x03bar\x00')
 
     def testDigestable2(self):
         n1 = dns.name.from_text('FOO.bar')
@@ -346,12 +343,12 @@ class NameTestCase(unittest.TestCase):
 
     def testDigestable3(self):
         d = dns.name.root.to_digestable()
-        self.failUnless(d == '\x00')
+        self.assertEqual(d, b'\x00')
 
     def testDigestable4(self):
         n = dns.name.from_text('FOO.bar', None)
         d = n.to_digestable(dns.name.root)
-        self.failUnless(d == '\x03foo\x03bar\x00')
+        self.assertEqual(d, b'\x03foo\x03bar\x00')
 
     def testBadDigestable(self):
         def bad():
@@ -361,56 +358,56 @@ class NameTestCase(unittest.TestCase):
 
     def testToWire1(self):
         n = dns.name.from_text('FOO.bar')
-        f = cStringIO.StringIO()
+        f = BytesIO()
         compress = {}
         n.to_wire(f, compress)
-        self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00')
+        self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00')
 
     def testToWire2(self):
         n = dns.name.from_text('FOO.bar')
-        f = cStringIO.StringIO()
+        f = BytesIO()
         compress = {}
         n.to_wire(f, compress)
         n.to_wire(f, compress)
-        self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00')
+        self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00')
 
     def testToWire3(self):
         n1 = dns.name.from_text('FOO.bar')
         n2 = dns.name.from_text('foo.bar')
-        f = cStringIO.StringIO()
+        f = BytesIO()
         compress = {}
         n1.to_wire(f, compress)
         n2.to_wire(f, compress)
-        self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00')
+        self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00')
 
     def testToWire4(self):
         n1 = dns.name.from_text('FOO.bar')
         n2 = dns.name.from_text('a.foo.bar')
-        f = cStringIO.StringIO()
+        f = BytesIO()
         compress = {}
         n1.to_wire(f, compress)
         n2.to_wire(f, compress)
-        self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\x01\x61\xc0\x00')
+        self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\x01\x61\xc0\x00')
 
     def testToWire5(self):
         n1 = dns.name.from_text('FOO.bar')
         n2 = dns.name.from_text('a.foo.bar')
-        f = cStringIO.StringIO()
+        f = BytesIO()
         compress = {}
         n1.to_wire(f, compress)
         n2.to_wire(f, None)
-        self.failUnless(f.getvalue() == \
-                        '\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00')
+        self.assertEqual(f.getvalue(),
+                         b'\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00')
 
     def testToWire6(self):
         n = dns.name.from_text('FOO.bar')
         v = n.to_wire()
-        self.failUnless(v == '\x03FOO\x03bar\x00')
+        self.assertEqual(v, b'\x03FOO\x03bar\x00')
 
     def testBadToWire(self):
         def bad():
             n = dns.name.from_text('FOO.bar', None)
-            f = cStringIO.StringIO()
+            f = BytesIO()
             compress = {}
             n.to_wire(f, compress)
         self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad)
@@ -551,7 +548,7 @@ class NameTestCase(unittest.TestCase):
                         n2 == en2 and cused2 == ecused2)
 
     def testFromWire1(self):
-        w = '\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05'
+        w = b'\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05'
         current = 0
         (n1, cused1) = dns.name.from_wire(w, current)
         current += cused1
@@ -570,25 +567,25 @@ class NameTestCase(unittest.TestCase):
 
     def testBadFromWire1(self):
         def bad():
-            w = '\x03foo\xc0\x04'
+            w = b'\x03foo\xc0\x04'
             (n, cused) = dns.name.from_wire(w, 0)
         self.failUnlessRaises(dns.name.BadPointer, bad)
 
     def testBadFromWire2(self):
         def bad():
-            w = '\x03foo\xc0\x05'
+            w = b'\x03foo\xc0\x05'
             (n, cused) = dns.name.from_wire(w, 0)
         self.failUnlessRaises(dns.name.BadPointer, bad)
 
     def testBadFromWire3(self):
         def bad():
-            w = '\xbffoo'
+            w = b'\xbffoo'
             (n, cused) = dns.name.from_wire(w, 0)
         self.failUnlessRaises(dns.name.BadLabelType, bad)
 
     def testBadFromWire4(self):
         def bad():
-            w = '\x41foo'
+            w = b'\x41foo'
             (n, cused) = dns.name.from_wire(w, 0)
         self.failUnlessRaises(dns.name.BadLabelType, bad)
 
@@ -616,48 +613,48 @@ class NameTestCase(unittest.TestCase):
 
     def testFromUnicode1(self):
         n = dns.name.from_text(u'foo.bar')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b''))
 
     def testFromUnicode2(self):
         n = dns.name.from_text(u'foo\u1234bar.bar')
-        self.failUnless(n.labels == ('xn--foobar-r5z', 'bar', ''))
+        self.assertEqual(n.labels, (b'xn--foobar-r5z', b'bar', b''))
 
     def testFromUnicodeAlternateDot1(self):
         n = dns.name.from_text(u'foo\u3002bar')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b''))
 
     def testFromUnicodeAlternateDot2(self):
         n = dns.name.from_text(u'foo\uff0ebar')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b''))
 
     def testFromUnicodeAlternateDot3(self):
         n = dns.name.from_text(u'foo\uff61bar')
-        self.failUnless(n.labels == ('foo', 'bar', ''))
+        self.assertEqual(n.labels, (b'foo', b'bar', b''))
 
     def testToUnicode1(self):
         n = dns.name.from_text(u'foo.bar')
         s = n.to_unicode()
-        self.failUnless(s == u'foo.bar.')
+        self.assertEqual(s, u'foo.bar.')
 
     def testToUnicode2(self):
         n = dns.name.from_text(u'foo\u1234bar.bar')
         s = n.to_unicode()
-        self.failUnless(s == u'foo\u1234bar.bar.')
+        self.assertEqual(s, u'foo\u1234bar.bar.')
 
     def testToUnicode3(self):
         n = dns.name.from_text('foo.bar')
         s = n.to_unicode()
-        self.failUnless(s == u'foo.bar.')
+        self.assertEqual(s, u'foo.bar.')
 
     def testReverseIPv4(self):
         e = dns.name.from_text('1.0.0.127.in-addr.arpa.')
         n = dns.reversename.from_address('127.0.0.1')
-        self.failUnless(e == n)
+        self.assertEqual(e, n)
 
     def testReverseIPv6(self):
         e = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.')
-        n = dns.reversename.from_address('::1')
-        self.failUnless(e == n)
+        n = dns.reversename.from_address(b'::1')
+        self.assertEqual(e, n)
 
     def testReverseIPv6MappedIpv4(self):
         e = dns.name.from_text('1.0.0.127.in-addr.arpa.')
@@ -676,15 +673,15 @@ class NameTestCase(unittest.TestCase):
 
     def testForwardIPv4(self):
         n = dns.name.from_text('1.0.0.127.in-addr.arpa.')
-        e = '127.0.0.1'
+        e = b'127.0.0.1'
         text = dns.reversename.to_address(n)
-        self.failUnless(text == e)
+        self.assertEqual(text, e)
 
     def testForwardIPv6(self):
         n = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.')
-        e = '::1'
+        e = b'::1'
         text = dns.reversename.to_address(n)
-        self.failUnless(text == e)
+        self.assertEqual(text, e)
 
     def testE164ToEnum(self):
         text = '+1 650 555 1212'
@@ -694,9 +691,9 @@ class NameTestCase(unittest.TestCase):
 
     def testEnumToE164(self):
         n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
-        e = '+16505551212'
+        e = b'+16505551212'
         text = dns.e164.to_e164(n)
-        self.failUnless(text == e)
+        self.assertEqual(text,e)
 
 if __name__ == '__main__':
     unittest.main()
Index: dnspython-1.12.0/tests/test_ntoaaton.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_ntoaaton.py
+++ dnspython-1.12.0/tests/test_ntoaaton.py
@@ -18,6 +18,7 @@ import unittest
 import dns.exception
 import dns.ipv4
 import dns.ipv6
+import binascii
 
 # for convenience
 aton4 = dns.ipv4.inet_aton
@@ -25,7 +26,7 @@ ntoa4 = dns.ipv4.inet_ntoa
 aton6 = dns.ipv6.inet_aton
 ntoa6 = dns.ipv6.inet_ntoa
 
-v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', '01.1.1.1',
+v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', #'01.1.1.1',
                 '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4',
                 '1.2.3.4.']
 
@@ -49,8 +50,8 @@ class NtoAAtoNTestCase(unittest.TestCase
 
     def test_aton5(self):
         a = aton6('1:2:3:4:5:6:7:8')
-        self.failUnless(a == \
-                        '00010002000300040005000600070008'.decode('hex_codec'))
+        self.assertEqual(a,
+                        binascii.unhexlify(b'00010002000300040005000600070008'))
 
     def test_bad_aton1(self):
         def bad():
@@ -69,89 +70,89 @@ class NtoAAtoNTestCase(unittest.TestCase
 
     def test_aton1(self):
         a = aton6('::')
-        self.failUnless(a == '\x00' * 16)
+        self.assertEqual(a, b'\x00' * 16)
 
     def test_aton2(self):
         a = aton6('::1')
-        self.failUnless(a == '\x00' * 15 + '\x01')
+        self.assertEqual(a, b'\x00' * 15 + b'\x01')
 
     def test_aton3(self):
         a = aton6('::10.0.0.1')
-        self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01')
+        self.assertEqual(a, b'\x00' * 12 + b'\x0a\x00\x00\x01')
 
     def test_aton4(self):
         a = aton6('abcd::dcba')
-        self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba')
+        self.assertEqual(a, b'\xab\xcd' + b'\x00' * 12 + b'\xdc\xba')
 
     def test_ntoa1(self):
-        b = '00010002000300040005000600070008'.decode('hex_codec')
+        b = binascii.unhexlify(b'00010002000300040005000600070008')
         t = ntoa6(b)
-        self.failUnless(t == '1:2:3:4:5:6:7:8')
+        self.assertEqual(t, b'1:2:3:4:5:6:7:8')
 
     def test_ntoa2(self):
-        b = '\x00' * 16
+        b = b'\x00' * 16
         t = ntoa6(b)
-        self.failUnless(t == '::')
+        self.assertEqual(t, b'::')
 
     def test_ntoa3(self):
-        b = '\x00' * 15 + '\x01'
+        b = b'\x00' * 15 + b'\x01'
         t = ntoa6(b)
-        self.failUnless(t == '::1')
+        self.assertEqual(t, b'::1')
 
     def test_ntoa4(self):
-        b = '\x80' + '\x00' * 15
+        b = b'\x80' + b'\x00' * 15
         t = ntoa6(b)
-        self.failUnless(t == '8000::')
+        self.assertEqual(t, b'8000::')
 
     def test_ntoa5(self):
-        b = '\x01\xcd' + '\x00' * 12 + '\x03\xef'
+        b = b'\x01\xcd' + b'\x00' * 12 + b'\x03\xef'
         t = ntoa6(b)
-        self.failUnless(t == '1cd::3ef')
+        self.assertEqual(t, b'1cd::3ef')
 
     def test_ntoa6(self):
-        b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec')
+        b = binascii.unhexlify(b'ffff00000000ffff000000000000ffff')
         t = ntoa6(b)
-        self.failUnless(t == 'ffff:0:0:ffff::ffff')
+        self.assertEqual(t, b'ffff:0:0:ffff::ffff')
 
     def test_ntoa7(self):
-        b = '00000000ffff000000000000ffffffff'.decode('hex_codec')
+        b = binascii.unhexlify(b'00000000ffff000000000000ffffffff')
         t = ntoa6(b)
-        self.failUnless(t == '0:0:ffff::ffff:ffff')
+        self.assertEqual(t, b'0:0:ffff::ffff:ffff')
 
     def test_ntoa8(self):
-        b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec')
+        b = binascii.unhexlify(b'ffff0000ffff00000000ffff00000000')
         t = ntoa6(b)
-        self.failUnless(t == 'ffff:0:ffff::ffff:0:0')
+        self.assertEqual(t, b'ffff:0:ffff::ffff:0:0')
 
     def test_ntoa9(self):
-        b = '0000000000000000000000000a000001'.decode('hex_codec')
+        b = binascii.unhexlify(b'0000000000000000000000000a000001')
         t = ntoa6(b)
-        self.failUnless(t == '::10.0.0.1')
+        self.assertEqual(t, b'::10.0.0.1')
 
     def test_ntoa10(self):
-        b = '0000000000000000000000010a000001'.decode('hex_codec')
+        b = binascii.unhexlify(b'0000000000000000000000010a000001')
         t = ntoa6(b)
-        self.failUnless(t == '::1:a00:1')
+        self.assertEqual(t, b'::1:a00:1')
 
     def test_ntoa11(self):
-        b = '00000000000000000000ffff0a000001'.decode('hex_codec')
+        b = binascii.unhexlify(b'00000000000000000000ffff0a000001')
         t = ntoa6(b)
-        self.failUnless(t == '::ffff:10.0.0.1')
+        self.assertEqual(t, b'::ffff:10.0.0.1')
 
     def test_ntoa12(self):
-        b = '000000000000000000000000ffffffff'.decode('hex_codec')
+        b = binascii.unhexlify(b'000000000000000000000000ffffffff')
         t = ntoa6(b)
-        self.failUnless(t == '::255.255.255.255')
+        self.assertEqual(t, b'::255.255.255.255')
 
     def test_ntoa13(self):
-        b = '00000000000000000000ffffffffffff'.decode('hex_codec')
+        b = binascii.unhexlify(b'00000000000000000000ffffffffffff')
         t = ntoa6(b)
-        self.failUnless(t == '::ffff:255.255.255.255')
+        self.assertEqual(t, b'::ffff:255.255.255.255')
 
     def test_ntoa14(self):
-        b = '0000000000000000000000000001ffff'.decode('hex_codec')
+        b = binascii.unhexlify(b'0000000000000000000000000001ffff')
         t = ntoa6(b)
-        self.failUnless(t == '::0.1.255.255')
+        self.assertEqual(t, b'::0.1.255.255')
 
     def test_bad_ntoa1(self):
         def bad():
@@ -164,14 +165,14 @@ class NtoAAtoNTestCase(unittest.TestCase
         self.failUnlessRaises(ValueError, bad)
 
     def test_good_v4_aton(self):
-        pairs = [('1.2.3.4', '\x01\x02\x03\x04'),
-                 ('255.255.255.255', '\xff\xff\xff\xff'),
-                 ('0.0.0.0', '\x00\x00\x00\x00')]
+        pairs = [(b'1.2.3.4', b'\x01\x02\x03\x04'),
+                 (b'255.255.255.255', b'\xff\xff\xff\xff'),
+                 (b'0.0.0.0', b'\x00\x00\x00\x00')]
         for (t, b) in pairs:
             b1 = aton4(t)
             t1 = ntoa4(b1)
-            self.failUnless(b1 == b)
-            self.failUnless(t1 == t)
+            self.assertEqual(b1, b)
+            self.assertEqual(t1, t)
 
     def test_bad_v4_aton(self):
         def make_bad(a):
@@ -179,6 +180,7 @@ class NtoAAtoNTestCase(unittest.TestCase
                 return aton4(a)
             return bad
         for addr in v4_bad_addrs:
+            print(addr)
             self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr))
 
     def test_bad_v6_aton(self):
@@ -194,10 +196,10 @@ class NtoAAtoNTestCase(unittest.TestCase
             self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr))
 
     def test_rfc5952_section_4_2_2(self):
-        addr = '2001:db8:0:1:1:1:1:1'
+        addr = b'2001:db8:0:1:1:1:1:1'
         b1 = aton6(addr)
         t1 = ntoa6(b1)
-        self.failUnless(t1 == addr)
+        self.assertEqual(t1, addr)
 
     def test_is_mapped(self):
         t1 = '2001:db8:0:1:1:1:1:1'
Index: dnspython-1.12.0/tests/test_resolver.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_resolver.py
+++ dnspython-1.12.0/tests/test_resolver.py
@@ -13,7 +13,7 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+from io import StringIO
 import select
 import sys
 import time
@@ -25,8 +25,9 @@ import dns.name
 import dns.rdataclass
 import dns.rdatatype
 import dns.resolver
+from dns._compat import xrange
 
-resolv_conf = """
+resolv_conf = u"""
     /t/t
 # comment 1
 ; comment 2
@@ -55,7 +56,7 @@ class BaseResolverTests(object):
 
     if sys.platform != 'win32':
         def testRead(self):
-            f = cStringIO.StringIO(resolv_conf)
+            f = StringIO(resolv_conf)
             r = dns.resolver.Resolver(f)
             self.failUnless(r.nameservers == ['10.0.0.1', '10.0.0.2'] and
                             r.domain == dns.name.from_text('foo'))
Index: dnspython-1.12.0/tests/test_tokenizer.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_tokenizer.py
+++ dnspython-1.12.0/tests/test_tokenizer.py
@@ -14,6 +14,10 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import dns.exception
 import dns.tokenizer
Index: dnspython-1.12.0/tests/test_update.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_update.py
+++ dnspython-1.12.0/tests/test_update.py
@@ -18,6 +18,7 @@ import unittest
 import dns.update
 import dns.rdata
 import dns.rdataset
+import binascii
 
 goodhex = '0001 2800 0001 0005 0007 0000' \
           '076578616d706c6500 0006 0001' \
@@ -34,7 +35,7 @@ goodhex = '0001 2800 0001 0005 0007 0000
           '04626c617ac00c 0001 00ff 00000000 0000' \
           'c049 00ff 00ff 00000000 0000'
 
-goodwire = goodhex.replace(' ', '').decode('hex_codec')
+goodwire = binascii.unhexlify(goodhex.replace(' ', '').encode())
 
 update_text="""id 1
 opcode UPDATE
Index: dnspython-1.12.0/tests/test_zone.py
===================================================================
--- dnspython-1.12.0.orig/tests/test_zone.py
+++ dnspython-1.12.0/tests/test_zone.py
@@ -13,7 +13,7 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import cStringIO
+from io import BytesIO, StringIO
 import filecmp
 import os
 import unittest
@@ -25,6 +25,9 @@ import dns.rdatatype
 import dns.rrset
 import dns.zone
 
+def here(filename):
+    return os.path.join(os.path.dirname(__file__), filename)
+
 example_text = """$TTL 3600
 $ORIGIN example.
 @ soa foo bar 1 2 3 4 5
@@ -83,8 +86,8 @@ $ORIGIN example.
 @ soa foo bar 1 2 3 4 5
 """
 
-include_text = """$INCLUDE "example"
-"""
+include_text = """$INCLUDE "%s"
+""" % here("example")
 
 bad_directive_text = """$FOO bar
 $ORIGIN example.
@@ -95,54 +98,61 @@ ns1 1d1s a 10.0.0.1
 ns2 1w1D1h1m1S a 10.0.0.2
 """
 
-_keep_output = False
+_keep_output = True
+
+def _rdata_sort(a):
+    return (a[0], a[2].rdclass, a[2].to_text())
 
 class ZoneTestCase(unittest.TestCase):
 
     def testFromFile1(self):
-        z = dns.zone.from_file('example', 'example')
+        z = dns.zone.from_file(here('example'), 'example')
         ok = False
         try:
-            z.to_file('example1.out', nl='\x0a')
-            ok = filecmp.cmp('example1.out', 'example1.good')
+            z.to_file(here('example1.out'), nl=b'\x0a')
+            ok = filecmp.cmp(here('example1.out'),
+                             here('example1.good'))
         finally:
             if not _keep_output:
-                os.unlink('example1.out')
+                os.unlink(here('example1.out'))
         self.failUnless(ok)
 
     def testFromFile2(self):
-        z = dns.zone.from_file('example', 'example', relativize=False)
+        z = dns.zone.from_file(here('example'), 'example', relativize=False)
         ok = False
         try:
-            z.to_file('example2.out', relativize=False, nl='\x0a')
-            ok = filecmp.cmp('example2.out', 'example2.good')
+            z.to_file(here('example2.out'), relativize=False, nl=b'\x0a')
+            ok = filecmp.cmp(here('example2.out'),
+                             here('example2.good'))
         finally:
             if not _keep_output:
-                os.unlink('example2.out')
+                os.unlink(here('example2.out'))
         self.failUnless(ok)
 
     def testToText(self):
-        z = dns.zone.from_file('example', 'example')
+        z = dns.zone.from_file(here('example'), 'example')
         ok = False
         try:
-            text_zone = z.to_text(nl='\x0a')
-            f = open('example3.out', 'wb')
+            text_zone = z.to_text(nl=b'\x0a')
+            f = open(here('example3.out'), 'wb')
             f.write(text_zone)
             f.close()
-            ok = filecmp.cmp('example3.out', 'example3.good')
+            ok = filecmp.cmp(here('example3.out'),
+                             here('example3.good'))
         finally:
             if not _keep_output:
-                os.unlink('example3.out')
+                os.unlink(here('example3.out'))
         self.failUnless(ok)
 
     def testFromText(self):
         z = dns.zone.from_text(example_text, 'example.', relativize=True)
-        f = cStringIO.StringIO()
-        names = z.nodes.keys()
+        f = StringIO()
+        names = list(z.nodes.keys())
         names.sort()
         for n in names:
-            print >> f, z[n].to_text(n)
-        self.failUnless(f.getvalue() == example_text_output)
+            f.write(z[n].to_text(n))
+            f.write(u'\n')
+        self.assertEqual(f.getvalue(), example_text_output)
 
     def testTorture1(self):
         #
@@ -150,10 +160,10 @@ class ZoneTestCase(unittest.TestCase):
         # for each RR in the zone, convert the rdata into wire format
         # and then back out, and see if we get equal rdatas.
         #
-        f = cStringIO.StringIO()
+        f = BytesIO()
         o = dns.name.from_text('example.')
-        z = dns.zone.from_file('example', o)
-        for (name, node) in z.iteritems():
+        z = dns.zone.from_file(here('example'), o)
+        for (name, node) in z.items():
             for rds in node:
                 for rd in rds:
                     f.seek(0)
@@ -336,7 +346,7 @@ class ZoneTestCase(unittest.TestCase):
     def testIterateAllRdatas(self):
         z = dns.zone.from_text(example_text, 'example.', relativize=True)
         l = list(z.iterate_rdatas())
-        l.sort()
+        l.sort(key=_rdata_sort)
         exl = [(dns.name.from_text('@', None),
                 3600,
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
@@ -361,6 +371,7 @@ class ZoneTestCase(unittest.TestCase):
                 3600,
                 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
                                     '10.0.0.2'))]
+        exl.sort(key=_rdata_sort)
         self.failUnless(l == exl)
 
     def testTTLs(self):
@@ -390,7 +401,7 @@ class ZoneTestCase(unittest.TestCase):
     def testInclude(self):
         z1 = dns.zone.from_text(include_text, 'example.', relativize=True,
                                 allow_include=True)
-        z2 = dns.zone.from_file('example', 'example.', relativize=True)
+        z2 = dns.zone.from_file(here('example'), 'example.', relativize=True)
         self.failUnless(z1 == z2)
 
     def testBadDirective(self):
