]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
python3 support
authorArthur Gautier <baloo@gandi.net>
Tue, 29 Mar 2016 17:51:13 +0000 (17:51 +0000)
committerArthur Gautier <baloo@gandi.net>
Thu, 21 Apr 2016 15:33:05 +0000 (15:33 +0000)
Signed-off-by: Arthur Gautier <baloo@gandi.net>
100 files changed:
dns/_compat.py [new file with mode: 0644]
dns/dnssec.py
dns/e164.py
dns/edns.py
dns/entropy.py
dns/exception.py
dns/flags.py
dns/grange.py
dns/hash.py
dns/inet.py
dns/ipv4.py
dns/ipv6.py
dns/message.py
dns/name.py
dns/namedict.py
dns/node.py
dns/opcode.py
dns/query.py
dns/rcode.py
dns/rdata.py
dns/rdataclass.py
dns/rdataset.py
dns/rdatatype.py
dns/rdtypes/ANY/AFSDB.py
dns/rdtypes/ANY/CAA.py
dns/rdtypes/ANY/CDNSKEY.py
dns/rdtypes/ANY/CDS.py
dns/rdtypes/ANY/CERT.py
dns/rdtypes/ANY/CNAME.py
dns/rdtypes/ANY/DLV.py
dns/rdtypes/ANY/DNAME.py
dns/rdtypes/ANY/DNSKEY.py
dns/rdtypes/ANY/DS.py
dns/rdtypes/ANY/EUI48.py
dns/rdtypes/ANY/EUI64.py
dns/rdtypes/ANY/GPOS.py
dns/rdtypes/ANY/HINFO.py
dns/rdtypes/ANY/HIP.py
dns/rdtypes/ANY/ISDN.py
dns/rdtypes/ANY/LOC.py
dns/rdtypes/ANY/MX.py
dns/rdtypes/ANY/NS.py
dns/rdtypes/ANY/NSEC.py
dns/rdtypes/ANY/NSEC3.py
dns/rdtypes/ANY/NSEC3PARAM.py
dns/rdtypes/ANY/PTR.py
dns/rdtypes/ANY/RP.py
dns/rdtypes/ANY/RRSIG.py
dns/rdtypes/ANY/RT.py
dns/rdtypes/ANY/SOA.py
dns/rdtypes/ANY/SPF.py
dns/rdtypes/ANY/SSHFP.py
dns/rdtypes/ANY/TLSA.py
dns/rdtypes/ANY/TXT.py
dns/rdtypes/ANY/URI.py
dns/rdtypes/ANY/X25.py
dns/rdtypes/IN/A.py
dns/rdtypes/IN/AAAA.py
dns/rdtypes/IN/APL.py
dns/rdtypes/IN/DHCID.py
dns/rdtypes/IN/IPSECKEY.py
dns/rdtypes/IN/KX.py
dns/rdtypes/IN/NAPTR.py
dns/rdtypes/IN/NSAP.py
dns/rdtypes/IN/NSAP_PTR.py
dns/rdtypes/IN/PX.py
dns/rdtypes/IN/SRV.py
dns/rdtypes/IN/WKS.py
dns/rdtypes/dnskeybase.py
dns/rdtypes/dsbase.py
dns/rdtypes/euibase.py
dns/rdtypes/mxbase.py
dns/rdtypes/nsbase.py
dns/rdtypes/txtbase.py
dns/renderer.py
dns/resolver.py
dns/reversename.py
dns/rrset.py
dns/set.py
dns/tokenizer.py
dns/tsig.py
dns/tsigkeyring.py
dns/ttl.py
dns/update.py
dns/version.py
dns/wiredata.py
dns/zone.py
setup.py
tests/test_bugs.py
tests/test_dnssec.py
tests/test_generate.py
tests/test_grange.py
tests/test_message.py
tests/test_name.py
tests/test_ntoaaton.py
tests/test_rdtypeanyeui.py
tests/test_resolver.py
tests/test_tokenizer.py
tests/test_update.py
tests/test_zone.py

diff --git a/dns/_compat.py b/dns/_compat.py
new file mode 100644 (file)
index 0000000..88416ee
--- /dev/null
@@ -0,0 +1,19 @@
+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,)
+else:
+    text_type = unicode
+    binary_type = str
+    string_types = (basestring,)
index a4546450cd3d419e65ca08f87714a17e08921760..fec12082c8aa768880f6ed876cf6facf2c88c109 100644 (file)
@@ -15,7 +15,7 @@
 
 """Common DNSSEC-related functions and constants."""
 
-import cStringIO
+from io import BytesIO
 import struct
 import time
 
@@ -27,11 +27,16 @@ import dns.rdataset
 import dns.rdata
 import dns.rdatatype
 import dns.rdataclass
+from ._compat import string_types
+
 
 class UnsupportedAlgorithm(dns.exception.DNSException):
+
     """The DNSSEC algorithm is not supported."""
 
+
 class ValidationFailure(dns.exception.DNSException):
+
     """The DNSSEC signature is invalid."""
 
 RSAMD5 = 1
@@ -50,27 +55,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
@@ -81,6 +87,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"""
@@ -90,35 +97,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))
@@ -128,8 +140,9 @@ def make_ds(name, key, algorithm, origin=None):
     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
@@ -143,49 +156,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):
@@ -197,13 +220,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
@@ -217,7 +241,8 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
     @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
@@ -225,15 +250,15 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
     @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]
@@ -244,21 +269,21 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
         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),
@@ -288,14 +313,12 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
             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])
@@ -309,7 +332,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
             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))
@@ -320,7 +343,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
         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)
@@ -335,18 +358,20 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
             # 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
@@ -358,7 +383,8 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None):
     @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
@@ -366,7 +392,7 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None):
     @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):
@@ -384,18 +410,19 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None):
     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
@@ -417,9 +444,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 68f0a316a4fd896d8cbccf9385800ee84df244c9..2cc911cdbb5452249d149b9b53c4c83fbcec236e 100644 (file)
 @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_domain):
     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_domain, want_plus_prefix=True):
     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 cf062d06b6dd622897c609e1015077d0117a4433..c6102fd7ea1dfb0ff34a74346811256f2be63a95 100644 (file)
@@ -17,7 +17,9 @@
 
 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,23 +111,28 @@ 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)
+        return cls(otype, wire[current: current + olen])
 
     def _cmp(self, other):
-        return cmp(self.data, other.data)
+        if self.data == other.data:
+            return 0
+        if self.data > other.data:
+            return 1
+        return -1
 
 _type_to_class = {
 }
 
+
 def get_option_class(otype):
     cls = _type_to_class.get(otype)
     if cls is None:
         cls = GenericOption
     return cls
 
+
 def option_from_wire(otype, wire, current, olen):
     """Build an EDNS option object from wire format
 
index 1ffbc7b92b01d84749f27bb4933655560ff3a05d..43841a7a7522fa84e118853db5e1f13216800cd9 100644 (file)
 
 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,11 +103,11 @@ 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
@@ -116,8 +118,10 @@ class EntropyPool(object):
 
 pool = EntropyPool()
 
+
 def random_16():
     return pool.random_16()
 
+
 def between(first, last):
     return pool.random_between(first, last)
index cbcdb57c82cd61bb2de1332b120df5d86ecfed72..81c8daabebd8d2743fc992d4f8b0b66b01460904 100644 (file)
@@ -17,6 +17,7 @@
 
 
 class DNSException(Exception):
+
     """Abstract base class shared by all dnspython exceptions.
 
     It supports two basic modes of operation:
@@ -97,18 +98,27 @@ class DNSException(Exception):
 
 
 class FormError(DNSException):
+
     """DNS message is malformed."""
 
+
 class SyntaxError(DNSException):
+
     """Text input is malformed."""
 
+
 class UnexpectedEnd(SyntaxError):
+
     """Text input ended unexpectedly."""
 
+
 class TooBig(DNSException):
+
     """The DNS message is too big."""
 
+
 class Timeout(DNSException):
+
     """The DNS operation timed out."""
     supp_kwargs = set(['timeout'])
     fmt = "%s after {timeout} seconds" % __doc__[:-1]
index 35a8305e8093c8f503c275f091d0df6ade2bec39..388d6aaa732609054e1a843003a872a66bb275ad 100644 (file)
@@ -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 c0607d604e63f62243bc81d0917669e2b30b68eb..01a3257b79d357b94c20bc677e5bbed5cf14e690 100644 (file)
@@ -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 0c708036b1c259adca9019b5d19d1868351f9dec..27f7a7e2792d8267b785b55d507b1a152f743a1b 100644 (file)
 """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 3b7e88f7b1b767c377faee4fb12cd042e983e4db..966285e7e92b52fea17a4a94e4e9476fa60ce827 100644 (file)
@@ -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 85ab48f7d4e9767fcc0d2842394a14795f5f5a0d..3fef282b66faba6e40eac26fe91c386c77578e72 100644 (file)
@@ -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 bf658af175baaf73722b2bff516dc5327207c0c6..ee991e85b1ee33edd14d7db2e161641919c57058 100644 (file)
 """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 820376d74e45a0a48bb0dce2db2ab64d191f4507..5f82b45ac26d139e632bc084c9251eba6e5f483d 100644 (file)
@@ -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,28 +37,44 @@ import dns.renderer
 import dns.tsig
 import dns.wiredata
 
+from ._compat import long, xrange, string_types
+
+
 class ShortHeader(dns.exception.FormError):
+
     """The DNS packet passed to from_wire() is too short."""
 
+
 class TrailingJunk(dns.exception.FormError):
+
     """The DNS packet passed to from_wire() has extra junk at the end of it."""
 
+
 class UnknownHeaderField(dns.exception.DNSException):
+
     """The header field name was not recognized when converting from text
     into a message."""
 
+
 class BadEDNS(dns.exception.FormError):
+
     """OPT record occured somewhere other than the start of
     the additional data section."""
 
+
 class BadTSIG(dns.exception.FormError):
+
     """A TSIG record occured somewhere other than the end of
     the additional data section."""
 
+
 class UnknownTSIGKey(dns.exception.DNSException):
+
     """A TSIG with an unknown key was received."""
 
+
 class Message(object):
+
     """A DNS message.
 
     @ivar id: The query id; the default is a randomly chosen id.
@@ -166,7 +183,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()
@@ -180,41 +197,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
@@ -266,7 +287,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
@@ -320,9 +341,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:
@@ -332,7 +353,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
 
@@ -409,7 +430,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,
@@ -448,7 +469,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
@@ -460,7 +481,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
@@ -492,7 +514,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 = []
@@ -530,7 +552,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
@@ -549,7 +571,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.
@@ -593,12 +617,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,
@@ -623,15 +647,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
@@ -641,10 +665,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
@@ -663,31 +688,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:
@@ -700,7 +725,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
 
@@ -725,14 +750,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.
 
@@ -786,6 +811,7 @@ def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
 
 
 class _TextReader(object):
+
     """Text format reader.
 
     @ivar tok: the tokenizer
@@ -823,13 +849,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
@@ -839,7 +865,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:
@@ -847,7 +873,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))
@@ -858,7 +884,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
@@ -891,7 +917,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
@@ -934,7 +960,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):
@@ -989,6 +1015,7 @@ def from_text(text):
 
     return m
 
+
 def from_file(f):
     """Read the next text format message from the specified file.
 
@@ -998,15 +1025,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
@@ -1018,7 +1041,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.
@@ -1054,11 +1078,11 @@ def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
     @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
@@ -1068,6 +1092,7 @@ def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
     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 f8faf455be83cc2137fea16fb16253b3f4b70d1f..1fc56ed772f168ee5fa8c8c7b81c6d39f2ad1744 100644 (file)
 @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
 NAMERELN_EQUAL = 3
 NAMERELN_COMMONANCESTOR = 4
 
+
 class EmptyLabel(dns.exception.SyntaxError):
+
     """A DNS label is empty."""
 
+
 class BadEscape(dns.exception.SyntaxError):
+
     """An escaped code in a text format of DNS name is invalid."""
 
+
 class BadPointer(dns.exception.FormError):
+
     """A DNS compression pointer points forward instead of backward."""
 
+
 class BadLabelType(dns.exception.FormError):
+
     """The label type in DNS name wire format is unknown."""
 
+
 class NeedAbsoluteNameOrOrigin(dns.exception.DNSException):
+
     """An attempt was made to convert a non-absolute name to
     wire when there was also a non-absolute (or missing) origin."""
 
+
 class NameTooLong(dns.exception.FormError):
+
     """A DNS name is > 255 octets long."""
 
+
 class LabelTooLong(dns.exception.SyntaxError):
+
     """A DNS label is > 63 octets long."""
 
+
 class AbsoluteConcatenation(dns.exception.DNSException):
+
     """An attempt was made to append anything other than the
     empty name to an absolute DNS name."""
 
+
 class NoParent(dns.exception.DNSException):
+
     """An attempt was made to get the parent of the root name
     or the empty name."""
 
-_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.
@@ -85,24 +101,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"""
 
@@ -115,7 +145,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:
@@ -123,7 +153,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.
@@ -139,7 +179,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)
 
@@ -153,7 +193,7 @@ class Name(object):
         return Name(copy.deepcopy(self.labels, memo))
 
     def __getstate__(self):
-        return { 'labels' : self.labels }
+        return {'labels': self.labels}
 
     def __setstate__(self, state):
         super(Name, self).__setattr__('labels', state['labels'])
@@ -164,25 +204,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).
@@ -317,9 +357,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.
@@ -327,17 +367,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.
@@ -355,7 +395,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):
@@ -379,14 +420,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
@@ -401,7 +443,7 @@ class Name(object):
         """
 
         if file is None:
-            file = cStringIO.StringIO()
+            file = BytesIO()
             want_return = True
         else:
             want_return = False
@@ -417,22 +459,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:
@@ -474,8 +516,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.
@@ -496,7 +539,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
@@ -538,10 +581,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.
@@ -549,7 +593,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")
@@ -562,7 +606,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:
@@ -581,8 +625,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
                 if len(label) > 63:
@@ -604,72 +647,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
@@ -685,23 +731,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:
@@ -710,7 +756,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 b9024a7727703c0603e3d19e27aca032ea7c3f18..58e403440a6fd2e8e21cf890025a0e4282b2bf6d 100644 (file)
 
 """DNS name dictionary"""
 
-import dns.name
 import collections
+import dns.name
+from ._compat import xrange
+
 
 class NameDict(collections.MutableMapping):
 
@@ -46,7 +48,7 @@ class NameDict(collections.MutableMapping):
         self.max_depth_items = 0
         self.update(dict(*args, **kwargs))
 
-    def __update_max_depth(self,key):
+    def __update_max_depth(self, key):
         if len(key) == self.max_depth:
             self.max_depth_items = self.max_depth_items + 1
         elif len(key) > self.max_depth:
@@ -77,8 +79,8 @@ class NameDict(collections.MutableMapping):
     def __len__(self):
         return len(self.__store)
 
-    def has_key(self,key):
-        return self.__store.has_key(key)
+    def has_key(self, key):
+        return key in self.__store
 
     def get_deepest_match(self, name):
         """Find the deepest match to I{name} in the dictionary.
@@ -96,7 +98,7 @@ class NameDict(collections.MutableMapping):
             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)
index e74004f6d06397907b14e72917e0d5a0ff72da2c..7c25060e925665e4217c45b190facdd769d6876c 100644 (file)
 
 """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 40fe8d1ae09055cc7b57129e80cfc8d43b31a64b..2b2918e9939e76d15570c42e03dd992aaa75d178 100644 (file)
@@ -24,23 +24,25 @@ NOTIFY = 4
 UPDATE = 5
 
 _by_text = {
-    'QUERY' : QUERY,
-    'IQUERY' : IQUERY,
-    'STATUS' : STATUS,
-    'NOTIFY' : NOTIFY,
-    'UPDATE' : UPDATE
+    'QUERY': QUERY,
+    'IQUERY': IQUERY,
+    'STATUS': STATUS,
+    'NOTIFY': NOTIFY,
+    'UPDATE': UPDATE
 }
 
 # 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.
 
-_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):
+
     """An DNS opcode is unknown."""
 
+
 def from_text(text):
     """Convert text into an opcode.
 
@@ -59,23 +61,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.
 
@@ -84,12 +89,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.
 
@@ -97,7 +103,7 @@ def is_update(flags):
     @type flags: int
     @rtype: bool
     """
-    
+
     if (from_flags(flags) == UPDATE):
         return True
     return False
index 4e8089f554ff5306bc9b07194bbd09ca8c90ef4c..cfa3f172032cc22554937bb60385a2d3e0145fec 100644 (file)
@@ -30,19 +30,31 @@ import dns.name
 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):
+
     """A DNS query response came from an unexpected address or port."""
 
+
 class BadResponse(dns.exception.FormError):
+
     """A DNS query response does not respond to the question asked."""
 
+
 def _compute_expiration(timeout):
     if timeout is None:
         return None
     else:
         return time.time() + timeout
 
+
 def _poll_for(fd, readable, writable, error, timeout):
     """Poll polling backend.
     @param fd: File descriptor
@@ -73,6 +85,7 @@ def _poll_for(fd, readable, writable, error, timeout):
 
     return bool(event_list)
 
+
 def _select_for(fd, readable, writable, error, timeout):
     """Select polling backend.
     @param fd: File descriptor
@@ -101,6 +114,7 @@ def _select_for(fd, readable, writable, error, timeout):
 
     return bool((rcount or wcount or xcount))
 
+
 def _wait_for(fd, readable, writable, error, expiration):
     done = False
     while not done:
@@ -113,11 +127,12 @@ def _wait_for(fd, readable, writable, error, expiration):
         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.
@@ -134,12 +149,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
@@ -148,6 +166,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().
@@ -170,6 +189,7 @@ def _destination_and_source(af, where, port, source, source_port):
             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.
@@ -201,8 +221,8 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
     """
 
     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)
     begin_time = None
     try:
@@ -217,8 +237,8 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
             _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 '
@@ -237,6 +257,7 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         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.
@@ -253,6 +274,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
@@ -264,16 +286,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.
@@ -302,8 +326,8 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
     """
 
     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)
     begin_time = None
     try:
@@ -337,6 +361,7 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         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,
@@ -390,20 +415,20 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
     @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')
@@ -426,7 +451,6 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
     delete_mode = True
     expecting_SOA = False
     soa_rrset = None
-    soa_count = 0
     if relativize:
         origin = zone
         oname = dns.name.empty
@@ -446,16 +470,18 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
             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")
@@ -479,7 +505,8 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
             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
@@ -489,8 +516,8 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
                 # 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 372d724fa12235e0f62a7212dc0ab8460f275917..698ad25cc3dcb0c69a90895c9521a1d1b223b082 100644 (file)
@@ -16,6 +16,8 @@
 """DNS Result Codes."""
 
 import dns.exception
+from ._compat import long
+
 
 NOERROR = 0
 FORMERR = 1
@@ -31,30 +33,32 @@ NOTZONE = 10
 BADVERS = 16
 
 _by_text = {
-    'NOERROR' : NOERROR,
-    'FORMERR' : FORMERR,
-    'SERVFAIL' : SERVFAIL,
-    'NXDOMAIN' : NXDOMAIN,
-    'NOTIMP' : NOTIMP,
-    'REFUSED' : REFUSED,
-    'YXDOMAIN' : YXDOMAIN,
-    'YXRRSET' : YXRRSET,
-    'NXRRSET' : NXRRSET,
-    'NOTAUTH' : NOTAUTH,
-    'NOTZONE' : NOTZONE,
-    'BADVERS' : BADVERS
+    'NOERROR': NOERROR,
+    'FORMERR': FORMERR,
+    'SERVFAIL': SERVFAIL,
+    'NXDOMAIN': NXDOMAIN,
+    'NOTIMP': NOTIMP,
+    'REFUSED': REFUSED,
+    'YXDOMAIN': YXDOMAIN,
+    'YXRRSET': YXRRSET,
+    'NXRRSET': NXRRSET,
+    'NOTAUTH': NOTAUTH,
+    'NOTZONE': NOTZONE,
+    'BADVERS': BADVERS
 }
 
 # 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 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):
+
     """A DNS rcode is unknown."""
 
+
 def from_text(text):
     """Convert text into an rcode.
 
@@ -73,6 +77,7 @@ def from_text(text):
         raise UnknownRcode
     return v
 
+
 def from_flags(flags, ednsflags):
     """Return the rcode value encoded by flags and ednsflags.
 
@@ -89,6 +94,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.
 
@@ -104,6 +110,7 @@ def to_flags(value):
     ev = long(value & 0xff0) << 20
     return (v, ev)
 
+
 def to_text(value):
     """Convert rcode into text.
 
index ef0dddefdf5583dd6f7cdfe409b29c268e7d22a5..cb8c27436308c89fcfba6d5b196e94d93a1849e9 100644 (file)
@@ -25,7 +25,10 @@ default is 'dns.rdtypes'.  Changing this value will break the library.
 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,12 @@ import dns.rdataclass
 import dns.rdatatype
 import dns.tokenizer
 import dns.wiredata
+from ._compat import xrange, string_types, text_type
 
 _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 +51,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 +70,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 +90,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 +117,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 +166,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()
 
@@ -207,57 +206,59 @@ class Rdata(object):
         rdclass.  Return < 0 if self < other in the DNSSEC ordering,
         0 if self == other, and > 0 if self > other.
         """
-        return cmp(self.to_digestable(dns.name.root),
-                   other.to_digestable(dns.name.root))
+        our = self.to_digestable(dns.name.root)
+        their = other.to_digestable(dns.name.root)
+        if our == their:
+            return 0
+        if our > their:
+            return 1
+
+        return -1
 
     def __eq__(self, other):
         if not isinstance(other, Rdata):
             return False
-        if self.rdclass != other.rdclass or \
-           self.rdtype != other.rdtype:
+        if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
             return False
         return self._cmp(other) == 0
 
     def __ne__(self, other):
         if not isinstance(other, Rdata):
             return True
-        if self.rdclass != other.rdclass or \
-           self.rdtype != other.rdtype:
+        if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
             return True
         return self._cmp(other) != 0
 
     def __lt__(self, other):
         if not isinstance(other, Rdata) or \
-               self.rdclass != other.rdclass or \
-               self.rdtype != other.rdtype:
+                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
+
             return NotImplemented
         return self._cmp(other) < 0
 
     def __le__(self, other):
         if not isinstance(other, Rdata) or \
-               self.rdclass != other.rdclass or \
-               self.rdtype != other.rdtype:
+                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
             return NotImplemented
         return self._cmp(other) <= 0
 
     def __ge__(self, other):
         if not isinstance(other, Rdata) or \
-               self.rdclass != other.rdclass or \
-               self.rdtype != other.rdtype:
+                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
             return NotImplemented
         return self._cmp(other) >= 0
 
     def __gt__(self, other):
         if not isinstance(other, Rdata) or \
-               self.rdclass != other.rdclass or \
-               self.rdtype != other.rdtype:
+                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
             return NotImplemented
         return self._cmp(other) > 0
 
     def __hash__(self):
         return hash(self.to_digestable(dns.name.root))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         """Build an rdata object from text format.
 
         @param rdclass: The rdata class
@@ -275,9 +276,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
@@ -297,9 +297,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.
         """
@@ -308,6 +306,7 @@ class Rdata(object):
 
 
 class GenericRdata(Rdata):
+
     """Generate Rdata Class
 
     This class is used for rdata types for which we have no better
@@ -323,36 +322,37 @@ class GenericRdata(Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return r'\# %d ' % len(self.data) + _hexify(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):
         token = tok.get()
         if not token.is_identifier() or token.value != '\#':
-            raise dns.exception.SyntaxError(r'generic rdata does not start with \#')
+            raise dns.exception.SyntaxError(
+                r'generic rdata does not start with \#')
         length = tok.get_int()
         chunks = []
         while 1:
             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')
+            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):
+    def to_wire(self, file, compress=None, origin=None):
         file.write(self.data)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        return cls(rdclass, rdtype, wire[current : current + rdlen])
-
-    from_wire = classmethod(from_wire)
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        return cls(rdclass, rdtype, wire[current: current + rdlen])
 
 _rdata_modules = {}
 _module_prefix = 'dns.rdtypes'
 
+
 def get_rdata_class(rdclass, rdtype):
 
     def import_module(name):
@@ -386,7 +386,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
@@ -412,7 +413,7 @@ def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
     @type relativize: bool
     @rtype: dns.rdata.Rdata instance"""
 
-    if isinstance(tok, (str, unicode)):
+    if isinstance(tok, string_types):
         tok = dns.tokenizer.Tokenizer(tok)
     cls = get_rdata_class(rdclass, rdtype)
     if cls != GenericRdata:
@@ -432,7 +433,8 @@ def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
                              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 06afa867741250b5bfa055bbf5c4797be40fc8a7..17a4810d524bb7c2be8e662d65f00553737653a9 100644 (file)
@@ -35,39 +35,42 @@ NONE = 254
 ANY = 255
 
 _by_text = {
-    'RESERVED0' : RESERVED0,
-    'IN' : IN,
-    'CH' : CH,
-    'HS' : HS,
-    'NONE' : NONE,
-    'ANY' : ANY
-    }
+    'RESERVED0': RESERVED0,
+    'IN': IN,
+    'CH': CH,
+    'HS': HS,
+    'NONE': NONE,
+    'ANY': ANY
+}
 
 # 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.
 
-_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.
 
 _by_text.update({
-    'INTERNET' : IN,
-    'CHAOS' : CH,
-    'HESIOD' : HS
-    })
+    'INTERNET': IN,
+    'CHAOS': CH,
+    'HESIOD': HS
+})
 
 _metaclasses = {
-    NONE : True,
-    ANY : True
-    }
+    NONE: True,
+    ANY: True
+}
+
+_unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I)
 
-_unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I);
 
 class UnknownRdataclass(dns.exception.DNSException):
+
     """A DNS class is unknown."""
 
+
 def from_text(text):
     """Convert text into a DNS rdata class value.
     @param text: the text
@@ -80,13 +83,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
@@ -99,15 +103,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 9524979fff33259ac765a5274eb05c4bf40e952c..db266f2f09e2faf5a25843ccb19ab92d89310e25 100644 (file)
@@ -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,18 +24,25 @@ 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
 
+
 class DifferingCovers(dns.exception.DNSException):
+
     """An attempt was made to add a DNS SIG/RRSIG whose covered type
     is not the same as that of the other rdatas in the rdataset."""
 
+
 class IncompatibleTypes(dns.exception.DNSException):
+
     """An attempt was made to add DNS RR data of an incompatible type."""
 
+
 class Rdataset(dns.set.Set):
+
     """A DNS rdataset.
 
     @ivar rdclass: The class of the rdataset
@@ -108,7 +115,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:
@@ -183,15 +190,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
@@ -201,15 +208,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
         #
@@ -231,8 +239,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
@@ -272,6 +280,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.
@@ -279,9 +288,9 @@ def from_text_list(rdclass, rdtype, ttl, text_rdatas):
     @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)
@@ -290,6 +299,7 @@ def from_text_list(rdclass, rdtype, ttl, text_rdatas):
         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.
@@ -299,6 +309,7 @@ def from_text(rdclass, rdtype, ttl, *text_rdatas):
 
     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.
@@ -313,10 +324,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 8e98f4925b86df197508f77f6b238faeeca9c834..f4336fca35f7aa9f47379f31650dd1809c6b67cb 100644 (file)
@@ -99,99 +99,102 @@ TA = 32768
 DLV = 32769
 
 _by_text = {
-    'NONE' : NONE,
-    'A' : A,
-    'NS' : NS,
-    'MD' : MD,
-    'MF' : MF,
-    'CNAME' : CNAME,
-    'SOA' : SOA,
-    'MB' : MB,
-    'MG' : MG,
-    'MR' : MR,
-    'NULL' : NULL,
-    'WKS' : WKS,
-    'PTR' : PTR,
-    'HINFO' : HINFO,
-    'MINFO' : MINFO,
-    'MX' : MX,
-    'TXT' : TXT,
-    'RP' : RP,
-    'AFSDB' : AFSDB,
-    'X25' : X25,
-    'ISDN' : ISDN,
-    'RT' : RT,
-    'NSAP' : NSAP,
-    'NSAP-PTR' : NSAP_PTR,
-    'SIG' : SIG,
-    'KEY' : KEY,
-    'PX' : PX,
-    'GPOS' : GPOS,
-    'AAAA' : AAAA,
-    'LOC' : LOC,
-    'NXT' : NXT,
-    'SRV' : SRV,
-    'NAPTR' : NAPTR,
-    'KX' : KX,
-    'CERT' : CERT,
-    'A6' : A6,
-    'DNAME' : DNAME,
-    'OPT' : OPT,
-    'APL' : APL,
-    'DS' : DS,
-    'SSHFP' : SSHFP,
-    'IPSECKEY' : IPSECKEY,
-    'RRSIG' : RRSIG,
-    'NSEC' : NSEC,
-    'DNSKEY' : DNSKEY,
-    'DHCID' : DHCID,
-    'NSEC3' : NSEC3,
-    'NSEC3PARAM' : NSEC3PARAM,
-    'TLSA' : TLSA,
-    'HIP' : HIP,
-    'CDS' : CDS,
-    'CDNSKEY' : CDNSKEY,
-    'SPF' : SPF,
-    'UNSPEC' : UNSPEC,
+    'NONE': NONE,
+    'A': A,
+    'NS': NS,
+    'MD': MD,
+    'MF': MF,
+    'CNAME': CNAME,
+    'SOA': SOA,
+    'MB': MB,
+    'MG': MG,
+    'MR': MR,
+    'NULL': NULL,
+    'WKS': WKS,
+    'PTR': PTR,
+    'HINFO': HINFO,
+    'MINFO': MINFO,
+    'MX': MX,
+    'TXT': TXT,
+    'RP': RP,
+    'AFSDB': AFSDB,
+    'X25': X25,
+    'ISDN': ISDN,
+    'RT': RT,
+    'NSAP': NSAP,
+    'NSAP-PTR': NSAP_PTR,
+    'SIG': SIG,
+    'KEY': KEY,
+    'PX': PX,
+    'GPOS': GPOS,
+    'AAAA': AAAA,
+    'LOC': LOC,
+    'NXT': NXT,
+    'SRV': SRV,
+    'NAPTR': NAPTR,
+    'KX': KX,
+    'CERT': CERT,
+    'A6': A6,
+    'DNAME': DNAME,
+    'OPT': OPT,
+    'APL': APL,
+    'DS': DS,
+    'SSHFP': SSHFP,
+    'IPSECKEY': IPSECKEY,
+    'RRSIG': RRSIG,
+    'NSEC': NSEC,
+    'DNSKEY': DNSKEY,
+    'DHCID': DHCID,
+    'NSEC3': NSEC3,
+    'NSEC3PARAM': NSEC3PARAM,
+    'TLSA': TLSA,
+    'HIP': HIP,
+    'CDS': CDS,
+    'CDNSKEY': CDNSKEY,
+    'SPF': SPF,
+    'UNSPEC': UNSPEC,
     'EUI48': EUI48,
     'EUI64': EUI64,
-    'TKEY' : TKEY,
-    'TSIG' : TSIG,
-    'IXFR' : IXFR,
-    'AXFR' : AXFR,
-    'MAILB' : MAILB,
-    'MAILA' : MAILA,
-    'ANY' : ANY,
-    'URI' : URI,
-    'CAA' : CAA,
-    'TA' : TA,
-    'DLV' : DLV,
-    }
+    'TKEY': TKEY,
+    'TSIG': TSIG,
+    'IXFR': IXFR,
+    'AXFR': AXFR,
+    'MAILB': MAILB,
+    'MAILA': MAILA,
+    'ANY': ANY,
+    'URI': URI,
+    'CAA': CAA,
+    'TA': TA,
+    'DLV': DLV,
+}
 
 # 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.
 
-_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 = {
-    OPT : True
-    }
+    OPT: True
+}
 
 _singletons = {
-    SOA : True,
-    NXT : True,
-    DNAME : True,
-    NSEC : True,
+    SOA: True,
+    NXT: True,
+    DNAME: True,
+    NSEC: True,
     # CNAME is technically a singleton, but we allow multiple CNAMEs.
-    }
+}
+
+_unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I)
 
-_unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I);
 
 class UnknownRdatatype(dns.exception.DNSException):
+
     """DNS resource record type is unknown."""
 
+
 def from_text(text):
     """Convert text into a DNS rdata type value.
     @param text: the text
@@ -203,13 +206,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
@@ -221,25 +225,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 c729789afafab6bcceea061111b69b42f9997984..f3d5154038ab40fd3107c98cd89fb56ce808daf7 100644 (file)
@@ -15,7 +15,9 @@
 
 import dns.rdtypes.mxbase
 
+
 class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX):
+
     """AFSDB record
 
     @ivar subtype: the subtype value
index 15e0f622a10f4133c7c180a52a6645711c536762..e80d46939cb09893df7f54921d67361b5db6ad49 100644 (file)
@@ -19,7 +19,9 @@ import dns.exception
 import dns.rdata
 import dns.tokenizer
 
+
 class CAA(dns.rdata.Rdata):
+
     """CAA (Certification Authority Authorization) record
 
     @ivar flags: the flags
@@ -43,31 +45,30 @@ class CAA(dns.rdata.Rdata):
                                dns.rdata._escapify(self.tag),
                                dns.rdata._escapify(self.value))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         flags = tok.get_uint8()
-        tag = tok.get_string()
+        tag = tok.get_string().encode()
         if len(tag) > 255:
             raise dns.exception.SyntaxError("tag too long")
         if not tag.isalnum():
             raise dns.exception.SyntaxError("tag is not alphanumeric")
-        value = tok.get_string()
+        value = tok.get_string().encode()
         return cls(rdclass, rdtype, flags, tag, value)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
-        file.write(chr(self.flags))
+    def to_wire(self, file, compress=None, origin=None):
+        file.write(struct.pack('!B', self.flags))
         l = len(self.tag)
         assert l < 256
-        file.write(chr(l))
+        file.write(struct.pack('!B', l))
         file.write(self.tag)
         file.write(self.value)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (flags, l) = struct.unpack('!BB', wire[current : current + 2])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        (flags, l) = struct.unpack('!BB', wire[current: current + 2])
         current += 2
-        tag = wire[current : current + l].unwrap()
-        value = wire[current + l:current + rdlen - 2].unwrap()
+        tag = wire[current: current + l]
+        value = wire[current + l:current + rdlen - 2]
         return cls(rdclass, rdtype, flags, tag, value)
 
-    from_wire = classmethod(from_wire)
index 25cb3d8c459f1da473cbfdaffcbe0f1c02caae13..83f3d51fc9455b697bcea66ad65ceb2b1a996345 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import dns.rdtypes.dnskeybase
-from dns.rdtypes.dnskeybase import *
+from dns.rdtypes.dnskeybase import flags_to_text_set, flags_from_text_set
+
+
+__all__ = ['flags_to_text_set', 'flags_from_text_set']
+
 
 class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):
+
     """CDNSKEY record"""
index 15fe012fd509c48062962673dd81eca9700b82c7..e1abfc3687426a424a9645b37950143cd1908fc9 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.dsbase
 
+
 class CDS(dns.rdtypes.dsbase.DSBase):
+
     """CDS record"""
index df2ab07b31e90504ee961243a0cedfa261f6bcd6..b74544096dec723027b813534b761c9730de2cb8 100644 (file)
@@ -13,8 +13,8 @@
 # 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
@@ -22,34 +22,38 @@ import dns.rdata
 import dns.tokenizer
 
 _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 +82,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,29 +96,27 @@ 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)
index 6c6ab35ccdbcf1562d48cdde1940820fb5e0a26a..65cf570c7ae56159628e68fdb9dc134bd26a8eb1 100644 (file)
@@ -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 2a360b97746c172693393905e68ecdd6d98f42c0..cd1244c194944f4cd7c3e0f1f5c1aa9e50929906 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.dsbase
 
+
 class DLV(dns.rdtypes.dsbase.DSBase):
+
     """DLV record"""
index d864001190c1bfd3e8f593607eafce897f5a207f..dac97214a9a1b667787bd1f526b743c41e5ee0f2 100644 (file)
 
 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 cc64b6cc826918bc3aa774ddfa6add1a081c1fb0..e915e98bbdb3405c1532f98a602f5ab67af4d1a1 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import dns.rdtypes.dnskeybase
-from dns.rdtypes.dnskeybase import *
+from dns.rdtypes.dnskeybase import flags_to_text_set, flags_from_text_set
+
+
+__all__ = ['flags_to_text_set', 'flags_from_text_set']
+
 
 class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):
+
     """DNSKEY record"""
index 6c669cccfdd5c0482d0d0e9856dafe89c01914a5..577c8d8416180af908192205253153ceba2ce0de 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.dsbase
 
+
 class DS(dns.rdtypes.dsbase.DSBase):
+
     """DS record"""
index 6ddfa6a4827528bfdb06ebbe45ae2a1a23ce6cbc..aa260e205d08298646a600c4789522285c6fd6d8 100644 (file)
@@ -18,6 +18,7 @@ import dns.rdtypes.euibase
 
 
 class EUI48(dns.rdtypes.euibase.EUIBase):
+
     """EUI48 record
 
     @ivar fingerprint: 48-bit Extended Unique Identifier (EUI-48)
index 41abd7b710ad54b7beb396e502bfa1764219d13d..5eba350d8f86fb0170a7d37a4b07a7aa4a043e08 100644 (file)
@@ -18,6 +18,7 @@ import dns.rdtypes.euibase
 
 
 class EUI64(dns.rdtypes.euibase.EUIBase):
+
     """EUI64 record
 
     @ivar fingerprint: 64-bit Extended Unique Identifier (EUI-64)
index 399948114ff251d0f0b22fc6949483bb6c1f762e..a359a77123127a59e0b7409dae4b21bfbb7485c6 100644 (file)
 # 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
+
 
 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 +69,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,61 +80,58 @@ 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())
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @classmethod
+    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         latitude = tok.get_string()
         longitude = tok.get_string()
         altitude = tok.get_string()
         tok.get_eol()
         return cls(rdclass, rdtype, latitude, longitude, altitude)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
             raise dns.exception.FormError
-        latitude = wire[current : current + l].unwrap()
+        latitude = wire[current: current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
             raise dns.exception.FormError
-        longitude = wire[current : current + l].unwrap()
+        longitude = wire[current: current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
             raise dns.exception.FormError
-        altitude = wire[current : current + l].unwrap()
+        altitude = wire[current: current + l].unwrap()
         return cls(rdclass, rdtype, latitude, longitude, altitude)
 
-    from_wire = classmethod(from_wire)
-
     def _get_float_latitude(self):
         return float(self.latitude)
 
index 4fe7a0f93fb3cb6b885bcdbdf1c3285922435368..52298bc4249053841d788a806764dc048b6bc034 100644 (file)
 # 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
+
 
 class HINFO(dns.rdata.Rdata):
+
     """HINFO record
 
     @ivar cpu: the CPU type
@@ -30,48 +35,51 @@ 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))
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
             raise dns.exception.FormError
-        cpu = wire[current : current + l].unwrap()
+        cpu = wire[current:current + l].unwrap()
         current += l
         rdlen -= l
-        l = ord(wire[current])
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
             raise dns.exception.FormError
-        os = wire[current : current + l].unwrap()
+        os = wire[current: current + l].unwrap()
         return cls(rdclass, rdtype, cpu, os)
 
-    from_wire = classmethod(from_wire)
index 654d5c79135d96e20d87065a8c8dd9919a727de6..e0cd2755c5c1581529de99468bd7a03e8d7bd2db 100644 (file)
 # 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
 
+
 class HIP(dns.rdata.Rdata):
+
     """HIP record
 
     @ivar hit: the host identity tag
@@ -44,22 +46,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 +73,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 +82,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 +100,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)
index 0a5c01d5519ffa6783d89387bf514a5b948c85c0..01284a8253e145c79c7707a7ac75226bf914f6f4 100644 (file)
 # 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
+
 
 class ISDN(dns.rdata.Rdata):
+
     """ISDN record
 
     @ivar address: the ISDN address
@@ -30,8 +35,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 +51,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,39 +64,35 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        l = ord(wire[current])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l > rdlen:
             raise dns.exception.FormError
-        address = wire[current : current + l].unwrap()
+        address = wire[current: current + l].unwrap()
         current += l
         rdlen -= l
         if rdlen > 0:
-            l = ord(wire[current])
+            l = wire[current]
             current += 1
             rdlen -= 1
             if l != rdlen:
                 raise dns.exception.FormError
-            subaddress = wire[current : current + l].unwrap()
+            subaddress = wire[current: current + l].unwrap()
         else:
             subaddress = ''
         return cls(rdclass, rdtype, address, subaddress)
 
-    from_wire = classmethod(from_wire)
index 73bf79ef345c34116fd32d9a82423e55e3ca6186..a4655d88b52886d511e2c99324c82b37eb9fe3c3 100644 (file)
 # 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
 
-_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 +57,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 +70,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 +87,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 +112,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 +155,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 +183,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 +216,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:
@@ -230,35 +243,33 @@ class LOC(dns.rdata.Rdata):
 
         t = tok.get_string()
         if t[-1] == 'm':
-            t = t[0 : -1]
+            t = t[0: -1]
         altitude = float(t) * 100.0        # m -> cm
 
         token = tok.get().unescape()
         if not token.is_eol_or_eof():
             value = token.value
             if value[-1] == 'm':
-                value = value[0 : -1]
+                value = value[0: -1]
             size = float(value) * 100.0        # m -> cm
             token = tok.get().unescape()
             if not token.is_eol_or_eof():
                 value = token.value
                 if value[-1] == 'm':
-                    value = value[0 : -1]
+                    value = value[0: -1]
                 hprec = float(value) * 100.0        # m -> cm
                 token = tok.get().unescape()
                 if not token.is_eol_or_eof():
                     value = token.value
                     if value[-1] == 'm':
-                        value = value[0 : -1]
+                        value = value[0: -1]
                     vprec = float(value) * 100.0        # m -> cm
                     tok.get_eol()
 
         return cls(rdclass, rdtype, latitude, longitude, altitude,
                    size, hprec, vprec)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         if self.latitude[0] < 0:
             sign = -1
             degrees = long(-1 * self.latitude[0])
@@ -269,7 +280,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 +291,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 +300,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,8 +323,6 @@ class LOC(dns.rdata.Rdata):
         return cls(rdclass, rdtype, latitude, longitude, altitude,
                    size, hprec, vprec)
 
-    from_wire = classmethod(from_wire)
-
     def _get_float_latitude(self):
         return _tuple_to_float(self.latitude)
 
index c407c11a44ad1d1e31d713c3956d8e5137af6fdc..3a6735dc5b69e5777d96e3016b595ada8f9f1a19 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.mxbase
 
+
 class MX(dns.rdtypes.mxbase.MXBase):
+
     """MX record"""
index c3d0234994ca515dffcbb990cd407f654da68085..ae56d819ed12b1403508dd2419cddb800e4d0f51 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.nsbase
 
+
 class NS(dns.rdtypes.nsbase.NSBase):
+
     """NS record"""
index fd76cc433f0ebad2a929a9cffc13a745cd9fce9e..dfe96859ff421ff2f4fa43ad7473bc8876a31a3d 100644 (file)
 # 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,23 +106,21 @@ 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)
index 1ed391dc33ee8164b421a184240227ec6985b798..3982f4b457f0d169e0fee2dca3b17fecec4892e0 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 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
 
-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 +40,9 @@ SHA1 = 1
 # flag constants
 OPTOUT = 1
 
+
 class NSEC3(dns.rdata.Rdata):
+
     """NSEC3 record
 
     @ivar algorithm: the hash algorithm number
@@ -57,39 +66,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 +121,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 +131,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)
+            windows.append((window, bitmap[0:octets]))
+        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
+                   windows)
 
-    from_text = classmethod(from_text)
-
-    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,40 +152,41 @@ 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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
-                                                             wire[current : current + 5])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        (algorithm, flags, iterations, slen) = \
+            struct.unpack('!BBHB', wire[current: current + 5])
+
         current += 5
         rdlen -= 5
-        salt = wire[current : current + slen].unwrap()
+        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()
+        next = wire[current: current + nlen].unwrap()
         current += nlen
         rdlen -= nlen
         windows = []
         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)
+        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
+                   windows)
 
-    from_wire = classmethod(from_wire)
index e12b04fc7d1ab09ce7073289aa9ae443ae4799f7..b506282be4e61df69bea424a49e37a7da8b83e12 100644 (file)
 # 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 binascii
 
 import dns.exception
 import dns.rdata
+from dns._compat import text_type
+
 
 class NSEC3PARAM(dns.rdata.Rdata):
+
     """NSEC3PARAM record
 
     @ivar algorithm: the hash algorithm number
@@ -38,16 +41,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,28 +63,27 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
-                                                             wire[current : current + 5])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        (algorithm, flags, iterations, slen) = \
+             struct.unpack('!BBHB',
+                           wire[current: current + 5])
         current += 5
         rdlen -= 5
-        salt = wire[current : current + slen].unwrap()
+        salt = wire[current: current + slen].unwrap()
         current += slen
         rdlen -= slen
         if rdlen != 0:
             raise dns.exception.FormError
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
 
-    from_wire = classmethod(from_wire)
index 963de63a1911db20e547412705882407c6ea7f2f..250187a61f0541352448dfd990e519cf256d69fc 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.nsbase
 
+
 class PTR(dns.rdtypes.nsbase.NSBase):
+
     """PTR record"""
index cb6b7c8d01b84c0f9b6e8bee1eda8c2a6f53ebaa..e9071c76342aafbbcd8c78b10e93dae894135ba9 100644 (file)
@@ -17,7 +17,9 @@ import dns.exception
 import dns.rdata
 import dns.name
 
+
 class RP(dns.rdata.Rdata):
+
     """RP record
 
     @ivar mbox: The responsible person's mailbox
@@ -39,7 +41,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 +50,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,13 +70,11 @@ 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)
index 7676a55df560035613545d37018468fcd91ad1a8..953dfb9a55f08451ddfa92c4640db30c8581267a 100644 (file)
@@ -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
@@ -22,9 +23,12 @@ import dns.exception
 import dns.rdata
 import dns.rdatatype
 
+
 class BadSigTime(dns.exception.DNSException):
+
     """Time in DNS SIG or RRSIG resource record cannot be parsed."""
 
+
 def sigtime_to_posixtime(what):
     if len(what) != 14:
         raise BadSigTime
@@ -37,10 +41,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
@@ -94,9 +101,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()
@@ -113,16 +121,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,
@@ -131,21 +137,20 @@ 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)
index 5ba9417bacb89f2dc8acaf35c3ea85022af1f237..88b75486807b777ed39005e4b761ac65717aab99 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.mxbase
 
+
 class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX):
+
     """RT record"""
index de786147054df4903421433c13ea45fbf1cc5e91..cc0098e8baaad8bf8fa0a304249853a84f7e7c63 100644 (file)
@@ -19,7 +19,9 @@ import dns.exception
 import dns.rdata
 import dns.name
 
+
 class SOA(dns.rdata.Rdata):
+
     """SOA record
 
     @ivar mname: the SOA MNAME (master name) field
@@ -58,9 +60,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 +75,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,16 +101,14 @@ 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)
index 1df95806c5933d8734e4fc5db8595ece8fb4655c..f3e0904e6f024a4a7b9cbb70c4117dd2ccbe2363 100644 (file)
@@ -15,7 +15,9 @@
 
 import dns.rdtypes.txtbase
 
+
 class SPF(dns.rdtypes.txtbase.TXTBase):
+
     """SPF record
 
     @see: RFC 4408"""
index f5a34c21a729d200ef23ec16eb7a2966bc9b283a..b6ed396f1d2897efeb5c6ce2155c58ad87a41ff7 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
 
+
 class SSHFP(dns.rdata.Rdata):
+
     """SSHFP record
 
     @ivar algorithm: the algorithm
@@ -44,7 +47,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,23 +58,21 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        header = struct.unpack("!BB", wire[current : current + 2])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        header = struct.unpack("!BB", wire[current: current + 2])
         current += 2
         rdlen -= 2
-        fingerprint = wire[current : current + rdlen].unwrap()
+        fingerprint = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], fingerprint)
 
-    from_wire = classmethod(from_wire)
index 92867ef3836d7094cd2a771f5df3b2041d02cfcb..23f4e94b1557e325f983cb6748ec8fc355b8d363 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
 
+
 class TLSA(dns.rdata.Rdata):
+
     """TLSA record
 
     @ivar usage: The certificate usage
@@ -46,9 +49,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,23 +63,21 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        header = struct.unpack("!BBB", wire[current : current + 3])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        header = struct.unpack("!BBB", wire[current: current + 3])
         current += 3
         rdlen -= 3
-        cert = wire[current : current + rdlen].unwrap()
+        cert = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2], cert)
 
-    from_wire = classmethod(from_wire)
index f921b36961529ff26eb539395a50218dcf46f09e..6c7fa4502e43874d51e8fd7279bcf43d5c632c54 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.txtbase
 
+
 class TXT(dns.rdtypes.txtbase.TXTBase):
+
     """TXT record"""
index 7ff6057c6959355518ce0cfa5f5ed0510c6a5f75..0c121d2c8a9d1d16467fd2b873270fe0e7ffb13d 100644 (file)
@@ -19,8 +19,11 @@ import struct
 import dns.exception
 import dns.rdata
 import dns.name
+from dns._compat import text_type
+
 
 class URI(dns.rdata.Rdata):
+
     """URI record
 
     @ivar priority: the priority
@@ -39,12 +42,17 @@ class URI(dns.rdata.Rdata):
         self.weight = weight
         if len(target) < 1:
             raise dns.exception.SyntaxError("URI target cannot be empty")
-        self.target = target
+        if isinstance(target, text_type):
+            self.target = target.encode()
+        else:
+            self.target = target
 
     def to_text(self, origin=None, relativize=True, **kw):
-        return '%d %d "%s"' % (self.priority, self.weight, self.target)
+        return '%d %d "%s"' % (self.priority, self.weight,
+                               self.target.decode())
 
-    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()
         target = tok.get().unescape()
@@ -53,23 +61,21 @@ class URI(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, priority, weight, target.value)
 
-    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.priority, self.weight)
         file.write(two_ints)
         file.write(self.target)
 
-    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 < 5:
             raise dns.exception.FormError('URI RR is shorter than 5 octets')
 
-        (priority, weight) = struct.unpack('!HH', wire[current : current + 4])
+        (priority, weight) = struct.unpack('!HH', wire[current: current + 4])
         current += 4
         rdlen -= 4
-        target = wire[current : current + rdlen]
+        target = wire[current: current + rdlen]
         current += rdlen
 
         return cls(rdclass, rdtype, priority, weight, target)
 
-    from_wire = classmethod(from_wire)
index 47671e4dd936c0378e4097bb0cf6cd5b92b0a638..f5cca114ef86c4d8de4294fb5d795f7a1ce0567f 100644 (file)
 # 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
+
 
 class X25(dns.rdata.Rdata):
+
     """X25 record
 
     @ivar address: the PSDN address
@@ -28,32 +33,33 @@ 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)
 
-    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()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    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])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        l = wire[current]
         current += 1
         rdlen -= 1
         if l != rdlen:
             raise dns.exception.FormError
-        address = wire[current : current + l].unwrap()
+        address = wire[current: current + l].unwrap()
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
index 945d93488ad7b4a041099953a32e3d5ea6e71332..42faf9baf76d6677348c348286570883f4bbcd35 100644 (file)
@@ -18,7 +18,9 @@ import dns.ipv4
 import dns.rdata
 import dns.tokenizer
 
+
 class A(dns.rdata.Rdata):
+
     """A record.
 
     @ivar address: an IPv4 address
@@ -29,24 +31,23 @@ 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
 
-    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_identifier()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         file.write(dns.ipv4.inet_aton(self.address))
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        address = dns.ipv4.inet_ntoa(wire[current : current + rdlen])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        address = dns.ipv4.inet_ntoa(wire[current: current + rdlen]).decode()
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
index 65be1c259724491177b555d24ae8d6f2ad2b2c64..d2c65c634ff072e0de993161c84cbb046db0b55a 100644 (file)
@@ -18,7 +18,9 @@ import dns.inet
 import dns.rdata
 import dns.tokenizer
 
+
 class AAAA(dns.rdata.Rdata):
+
     """AAAA record.
 
     @ivar address: an IPv6 address
@@ -29,25 +31,24 @@ class AAAA(dns.rdata.Rdata):
     def __init__(self, rdclass, rdtype, address):
         super(AAAA, self).__init__(rdclass, rdtype)
         # check that it's OK
-        junk = dns.inet.inet_pton(dns.inet.AF_INET6, address)
+        dns.inet.inet_pton(dns.inet.AF_INET6, address)
         self.address = address
 
     def to_text(self, origin=None, relativize=True, **kw):
         return 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_identifier()
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    from_text = classmethod(from_text)
-
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.address))
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @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])
+                                     wire[current: current + rdlen])
         return cls(rdclass, rdtype, address)
 
-    from_wire = classmethod(from_wire)
index 6239f078af7c807807184210565c0861a9f8bbbb..82026adfdc4c57e552c0000123d90bb1ce90342e 100644 (file)
 # 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 binascii
 
 import dns.exception
 import dns.inet
 import dns.rdata
 import dns.tokenizer
+from dns._compat import xrange
+
 
 class APLItem(object):
+
     """An APL list item.
 
     @ivar family: the address family (IANA address family registry)
@@ -54,7 +57,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 +66,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 +75,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 +93,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 +115,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 +138,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,4 +160,3 @@ class APL(dns.rdata.Rdata):
             items.append(item)
         return cls(rdclass, rdtype, items)
 
-    from_wire = classmethod(from_wire)
index 705e4a4e3d49777e79cd11128c236e3d7f7414cc..06a850ad293805b7dd9bf160b3a05d06021132ae 100644 (file)
 # 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
 
+
 class DHCID(dns.rdata.Rdata):
+
     """DHCID record
 
     @ivar data: the data (the content of the RR is opaque as far as the
@@ -32,7 +36,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,18 +45,16 @@ 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):
+    def to_wire(self, file, compress=None, origin=None):
         file.write(self.data)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        data = wire[current : current + rdlen].unwrap()
+    @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)
index d5d16bd87f7bfb96643e0e75dbd1d494645de558..4f07bd09e5d7e57e3b0f591304afe22c58e3556a 100644 (file)
 # 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.inet
 import dns.name
 
+
 class IPSECKEY(dns.rdata.Rdata):
+
     """IPSECKEY record
 
     @ivar precedence: the precedence for this key data
@@ -41,19 +43,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 +78,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 +94,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 +116,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 +128,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:
@@ -140,8 +143,7 @@ class IPSECKEY(dns.rdata.Rdata):
             rdlen -= cused
         else:
             raise dns.exception.FormError('invalid IPSECKEY gateway type')
-        key = wire[current : current + rdlen].unwrap()
+        key = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], gateway_type, header[2],
                    gateway, key)
 
-    from_wire = classmethod(from_wire)
index a01bddd10d54c82c5fe07edf5d48d82cef589d11..adbfe34b16a8a731443b6dbb25e44fa285fffa0b 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.mxbase
 
+
 class KX(dns.rdtypes.mxbase.UncompressedMX):
+
     """KX record"""
index 1357c6698d4cbed8111b7588698d969e7d983b08..5ae2feb15bc173f1c1d94a5e7394eb41ff8b68e0 100644 (file)
@@ -18,15 +18,24 @@ import struct
 import dns.exception
 import dns.name
 import dns.rdata
+from dns._compat import xrange, text_type
+
 
 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 +58,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 +72,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 +87,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 +95,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,13 +115,11 @@ 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)
index c20406399b95b8397bfc46849b7b13d03739d63e..6dbe5af09a876ff4fbecb78e80d175ead084821c 100644 (file)
 # 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
 
+
 class NSAP(dns.rdata.Rdata):
+
     """NSAP record.
 
     @ivar address: a NASP
@@ -31,26 +35,25 @@ 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()
 
-    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_eol()
+        tok.get_eol()
         if address[0:2] != '0x':
             raise dns.exception.SyntaxError('string does not start with 0x')
         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):
+    def to_wire(self, file, compress=None, origin=None):
         file.write(self.address)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        address = wire[current : current + rdlen].unwrap()
+    @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)
index 122c5123a067f57e701f4bd14752028b058979d9..56967df02d601667af34e12c49e5f197b584ccb4 100644 (file)
@@ -15,5 +15,7 @@
 
 import dns.rdtypes.nsbase
 
+
 class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS):
+
     """NSAP-PTR record"""
index 1b86789e2a7cbac0c72c5f98bba4d849a36dd24c..e1ef102b1f53d40ee8d0dc9beb466f776d230903 100644 (file)
@@ -19,7 +19,9 @@ import dns.exception
 import dns.rdata
 import dns.name
 
+
 class PX(dns.rdata.Rdata):
+
     """PX record.
 
     @ivar preference: the preference value
@@ -43,7 +45,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,36 +55,33 @@ 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)
index 5da202b8f734bcefc73f0e672678c35664d6eb52..f4396d61464458746080f4d1e2b870a9d524fe1d 100644 (file)
@@ -19,7 +19,9 @@ import dns.exception
 import dns.rdata
 import dns.name
 
+
 class SRV(dns.rdata.Rdata):
+
     """SRV record
 
     @ivar priority: the priority
@@ -46,7 +48,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,27 +58,24 @@ 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)
index 9d01504450b5def8b4d672e19e4f7c783c927dc2..da2a2d88ac28b351badc6f07e60ad3a050dcc530 100644 (file)
@@ -18,11 +18,14 @@ import struct
 
 import dns.ipv4
 import dns.rdata
+from dns._compat import xrange
 
 _proto_tcp = socket.getprotobyname('tcp')
 _proto_udp = socket.getprotobyname('udp')
 
+
 class WKS(dns.rdata.Rdata):
+
     """WKS record
 
     @ivar address: the address
@@ -39,26 +42,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,25 +84,23 @@ 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):
+    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)
 
-    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])
+    @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])
         current += 5
         rdlen -= 5
-        bitmap = wire[current : current + rdlen].unwrap()
+        bitmap = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, address, protocol, bitmap)
 
-    from_wire = classmethod(from_wire)
index 7e16085e5d67b4d110581860182d9bf6d1171fdf..85c4b23f01ce6c4327c196adf97215d78436c1f4 100644 (file)
@@ -21,7 +21,8 @@ import dns.dnssec
 import dns.rdata
 
 # wildcard import
-__all__ = [ "SEP", "REVOKE", "ZONE", "flags_to_text_set", "flags_from_text_set" ]
+__all__ = ["SEP", "REVOKE", "ZONE",
+           "flags_to_text_set", "flags_from_text_set"]
 
 # flag constants
 SEP = 0x0001
@@ -32,12 +33,13 @@ _flag_by_text = {
     'SEP': SEP,
     'REVOKE': REVOKE,
     'ZONE': ZONE
-    }
+}
 
 # 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.items()])
+_flag_by_value = dict((y, x) for x, y in _flag_by_text.items())
+
 
 def flags_to_text_set(flags):
     """Convert a DNSKEY flags value to set texts
@@ -68,7 +70,9 @@ def flags_from_text_set(texts_set):
                 "DNSKEY flag '%s' is not supported" % text)
     return flags
 
+
 class DNSKEYBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like a DNSKEY record
 
     @ivar flags: the key flags
@@ -93,7 +97,8 @@ class DNSKEYBase(dns.rdata.Rdata):
         return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
                                 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):
         flags = tok.get_uint16()
         protocol = tok.get_uint8()
         algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
@@ -104,30 +109,27 @@ class DNSKEYBase(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):
+    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)
 
-    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 < 4:
             raise dns.exception.FormError
-        header = struct.unpack('!HBB', wire[current : current + 4])
+        header = struct.unpack('!HBB', wire[current: current + 4])
         current += 4
         rdlen -= 4
-        key = wire[current : current + rdlen].unwrap()
+        key = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2],
                    key)
 
-    from_wire = classmethod(from_wire)
-
     def flags_to_text_set(self):
         """Convert a DNSKEY flags value to set texts
         @rtype: set([string])"""
index abcc57a73e87da508e91113d36a9fc599b8c37c6..80f792acfcacc95e3a09b1ff1b354f7746422b6f 100644 (file)
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import struct
+import binascii
 
 import dns.rdata
 import dns.rdatatype
 
+
 class DSBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like a DS record
 
     @ivar key_tag: the key tag
@@ -47,7 +50,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,25 +62,23 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
-        header = struct.unpack("!HBB", wire[current : current + 4])
+    @classmethod
+    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
+        header = struct.unpack("!HBB", wire[current: current + 4])
         current += 4
         rdlen -= 4
-        digest = wire[current : current + rdlen].unwrap()
+        digest = wire[current: current + rdlen].unwrap()
         return cls(rdclass, rdtype, header[0], header[1], header[2], digest)
 
-    from_wire = classmethod(from_wire)
index 2af018d4839004ac80c8d23d8b04420c39eb2efb..1310916373635a6ed29c83e4696497677db52552 100644 (file)
@@ -20,6 +20,7 @@ import dns.rdata
 
 
 class EUIBase(dns.rdata.Rdata):
+
     """EUIxx record
 
     @ivar fingerprint: xx-bit Extended Unique Identifier (EUI-xx)
@@ -41,6 +42,7 @@ class EUIBase(dns.rdata.Rdata):
     def to_text(self, origin=None, relativize=True, **kw):
         return dns.rdata._hexify(self.eui, chunksize=2).replace(' ', '-')
 
+    @classmethod
     def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
         text = tok.get_string()
         tok.get_eol()
@@ -54,18 +56,16 @@ class EUIBase(dns.rdata.Rdata):
                                                 % i)
         text = text.replace('-', '')
         try:
-            data = binascii.unhexlify(text)
+            data = binascii.unhexlify(text.encode())
         except (ValueError, TypeError) as ex:
             raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex))
         return cls(rdclass, rdtype, data)
 
-    from_text = classmethod(from_text)
-
     def to_wire(self, file, compress=None, origin=None):
         file.write(self.eui)
 
+    @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         eui = wire[current:current + rdlen].unwrap()
         return cls(rdclass, rdtype, eui)
 
-    from_wire = classmethod(from_wire)
index 754aff59a727b690510ab4028c3c7e9206e4871c..5ac8cef9ed70b029f88646650c7d429f60b262e6 100644 (file)
 
 """MX-like base classes."""
 
-import cStringIO
+from io import BytesIO
 import struct
 
 import dns.exception
 import dns.rdata
 import dns.name
 
+
 class MXBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like an MX record.
 
     @ivar preference: the preference value
@@ -41,57 +43,59 @@ class MXBase(dns.rdata.Rdata):
         exchange = self.exchange.choose_relativity(origin, relativize)
         return '%d %s' % (self.preference, exchange)
 
-    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()
         exchange = tok.get_name()
         exchange = exchange.choose_relativity(origin, relativize)
         tok.get_eol()
         return cls(rdclass, rdtype, preference, exchange)
 
-    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.exchange.to_wire(file, compress, origin)
 
-    def to_digestable(self, origin = None):
+    def to_digestable(self, origin=None):
         return struct.pack("!H", self.preference) + \
             self.exchange.to_digestable(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
         (exchange, 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:
             exchange = exchange.relativize(origin)
         return cls(rdclass, rdtype, preference, exchange)
 
-    from_wire = classmethod(from_wire)
-
-    def choose_relativity(self, origin = None, relativize = True):
+    def choose_relativity(self, origin=None, relativize=True):
         self.exchange = self.exchange.choose_relativity(origin, relativize)
 
+
 class UncompressedMX(MXBase):
+
     """Base class for rdata that is like an MX record, but whose name
     is not compressed when converted to DNS wire format, and whose
     digestable form is not downcased."""
 
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         super(UncompressedMX, 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()
 
+
 class UncompressedDowncasingMX(MXBase):
+
     """Base class for rdata that is like an MX record, but whose name
     is not compressed when convert to DNS wire format."""
 
-    def to_wire(self, file, compress = None, origin = None):
+    def to_wire(self, file, compress=None, origin=None):
         super(UncompressedDowncasingMX, self).to_wire(file, None, origin)
index 84f088a16417e47c0be2bbcdb95c9bf7e597f940..79333a14041297809499048d4bc29fe8cc61e6ec 100644 (file)
 
 """NS-like base classes."""
 
-import cStringIO
+from io import BytesIO
 
 import dns.exception
 import dns.rdata
 import dns.name
 
+
 class NSBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like an NS record.
 
     @ivar target: the target name of the rdata
@@ -37,43 +39,43 @@ class NSBase(dns.rdata.Rdata):
         target = self.target.choose_relativity(origin, relativize)
         return str(target)
 
-    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
+    @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):
+    def to_wire(self, file, compress=None, origin=None):
         self.target.to_wire(file, compress, origin)
 
-    def to_digestable(self, origin = None):
+    def to_digestable(self, origin=None):
         return self.target.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):
         (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):
+    def choose_relativity(self, origin=None, relativize=True):
         self.target = self.target.choose_relativity(origin, relativize)
 
+
 class UncompressedNS(NSBase):
+
     """Base class for rdata that is like an NS record, but whose name
     is not compressed when convert to DNS wire format, and whose
     digestable form is not downcased."""
 
-    def to_wire(self, file, compress = None, origin = None):
+    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 cf4b4cef9aa2f1b4eaa81425c84c944ba50a3d4c..54d7e6f0d33e8c447b286dceae1ca5c236aedd1f 100644 (file)
 
 """TXT-like base class."""
 
+import struct
+
 import dns.exception
 import dns.rdata
 import dns.tokenizer
+from dns._compat import binary_type
+
 
 class TXTBase(dns.rdata.Rdata):
+
     """Base class for rdata that is like a TXT record
 
     @ivar strings: the text strings
@@ -31,7 +36,7 @@ class TXTBase(dns.rdata.Rdata):
     def __init__(self, rdclass, rdtype, strings):
         super(TXTBase, self).__init__(rdclass, rdtype)
         if isinstance(strings, str):
-            strings = [ strings ]
+            strings = [strings]
         self.strings = strings[:]
 
     def to_text(self, origin=None, relativize=True, **kw):
@@ -42,7 +47,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,33 +58,34 @@ 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):
+    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)
 
-    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
+    @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:
                 raise dns.exception.FormError
-            s = wire[current : current + l].unwrap()
+            s = wire[current: current + l].unwrap()
             current += l
             rdlen -= l
             strings.append(s)
         return cls(rdclass, rdtype, strings)
 
-    from_wire = classmethod(from_wire)
index 1708e92a773df47301f3f17842f90db6215bbe3e..ed3ec66ef7c944839114a4b62b0180151ff6fa5b 100644 (file)
 
 """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 1835cde4886e528f3105abfe68d8a20763c22963..2b63792a6fbd8f9733d47b921abc0918b15f2e8c 100644 (file)
@@ -40,16 +40,19 @@ import dns.rdataclass
 import dns.rdatatype
 import dns.reversename
 import dns.tsig
+from ._compat import xrange, string_types
 
 if sys.platform == 'win32':
     import _winreg
 
+
 class NXDOMAIN(dns.exception.DNSException):
+
     """The DNS query name does not exist."""
     supp_kwargs = set(['qname'])
 
     def __str__(self):
-        if not 'qname' in self.kwargs:
+        if 'qname' not in self.kwargs:
             return super(NXDOMAIN, self).__str__()
 
         qname = self.kwargs['qname']
@@ -62,7 +65,9 @@ class NXDOMAIN(dns.exception.DNSException):
                 qname = qname[0]
         return "%s: %s" % (msg, (str(qname)))
 
+
 class YXDOMAIN(dns.exception.DNSException):
+
     """The DNS query name is too long after DNAME substitution."""
 
 # The definition of the Timeout exception has moved from here to the
@@ -73,6 +78,7 @@ Timeout = dns.exception.Timeout
 
 
 class NoAnswer(dns.exception.DNSException):
+
     """The DNS response does not contain an answer to the question."""
     fmt = '%s: {query}' % __doc__[:-1]
     supp_kwargs = set(['response'])
@@ -81,7 +87,9 @@ class NoAnswer(dns.exception.DNSException):
         return super(NoAnswer, self)._fmt_kwargs(
             query=kwargs['response'].question)
 
+
 class NoNameservers(dns.exception.DNSException):
+
     """All nameservers failed to answer the query.
 
     @param errors: list of servers and respective errors
@@ -103,15 +111,22 @@ class NoNameservers(dns.exception.DNSException):
 
 
 class NotAbsolute(dns.exception.DNSException):
+
     """An absolute domain name is required but a relative name was provided."""
 
+
 class NoRootSOA(dns.exception.DNSException):
+
     """There is no SOA RR at the DNS root name. This should never happen!"""
 
+
 class NoMetaqueries(dns.exception.DNSException):
+
     """DNS metaqueries are not allowed."""
 
+
 class Answer(object):
+
     """DNS stub resolver answer
 
     Instances of this class bundle up the result of a successful DNS
@@ -141,6 +156,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
@@ -184,7 +200,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:
@@ -229,7 +245,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
@@ -261,7 +279,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:
@@ -316,8 +334,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 = {}
@@ -325,9 +343,12 @@ class Cache(object):
         finally:
             self.lock.release()
 
+
 class LRUCacheNode(object):
+
     """LRUCache node.
     """
+
     def __init__(self, key, value):
         self.key = key
         self.value = value
@@ -350,7 +371,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
@@ -370,7 +393,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 = {}
@@ -418,7 +442,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:
@@ -442,9 +466,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:
@@ -458,7 +482,9 @@ class LRUCache(object):
         finally:
             self.lock.release()
 
+
 class Resolver(object):
+
     """DNS stub resolver
 
     @ivar domain: The domain of this host
@@ -492,7 +518,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
@@ -500,6 +527,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.
 
@@ -547,7 +575,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:
@@ -606,7 +634,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):
@@ -621,7 +649,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):
@@ -704,59 +732,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()
@@ -791,7 +819,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).
@@ -808,13 +837,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
@@ -834,13 +863,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)
@@ -877,10 +906,11 @@ class Resolver(object):
                                 # Response truncated; retry with TCP.
                                 tcp_attempt = True
                                 timeout = self._compute_timeout(start)
-                                response = dns.query.tcp(request, nameserver,
-                                                       timeout, port,
-                                                       source=source,
-                                                       source_port=source_port)
+                                response = \
+                                    dns.query.tcp(request, nameserver,
+                                                  timeout, port,
+                                                  source=source,
+                                                  source_port=source_port)
                     except (socket.error, dns.exception.Timeout) as ex:
                         #
                         # Communication failure or timeout.  Go to the
@@ -928,7 +958,7 @@ class Resolver(object):
                                        response))
                         raise ex
                     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
@@ -940,7 +970,7 @@ class Resolver(object):
                     errors.append((nameserver, tcp_attempt, port,
                                    dns.rcode.to_text(rcode), response))
                     response = None
-                if not response is None:
+                if response is not None:
                     break
                 #
                 # All nameservers failed!
@@ -1013,6 +1043,7 @@ class Resolver(object):
 
 default_resolver = None
 
+
 def get_default_resolver():
     """Get the default resolver, initializing it if necessary."""
     global default_resolver
@@ -1020,6 +1051,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):
@@ -1032,6 +1064,7 @@ def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
     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.
 
@@ -1045,7 +1078,7 @@ def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
     @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()
@@ -1070,9 +1103,9 @@ def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
 #
 
 _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
@@ -1082,9 +1115,10 @@ _original_gethostbyname = socket.gethostbyname
 _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)
@@ -1119,7 +1153,6 @@ def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
         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)
@@ -1182,6 +1215,7 @@ def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
         raise socket.gaierror(socket.EAI_NONAME)
     return tuples
 
+
 def _getnameinfo(sockaddr, flags=0):
     host = sockaddr[0]
     port = sockaddr[1]
@@ -1221,6 +1255,7 @@ def _getnameinfo(sockaddr, flags=0):
         service = socket.getservbyport(port, pname)
     return (hostname, service)
 
+
 def _getfqdn(name=None):
     if name is None:
         name = socket.gethostname()
@@ -1229,23 +1264,26 @@ def _getfqdn(name=None):
     except:
         return name
 
+
 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:
@@ -1262,6 +1300,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.
@@ -1287,6 +1326,7 @@ def override_system_resolver(resolver=None):
     socket.gethostbyname_ex = _gethostbyname_ex
     socket.gethostbyaddr = _gethostbyaddr
 
+
 def restore_system_resolver():
     """Undo the effects of override_system_resolver().
     """
index b80c60a0b19dd159baace79cb4db385c6682a8c2..a27e7050fc26e8f19d55e1efe52a90417863399f 100644 (file)
@@ -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 f6051fea4fc1a6134807c42c1ab796ac7d5f8677..6ad71da831a784eae65ecb4a2d72bfb570a20117 100644 (file)
 
 """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, rdtype, text_rdatas):
     @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, rdtype, text_rdatas):
         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, *text_rdatas):
 
     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 14c76a05c47df26b56604c0abff85cc9e256007e..f13af5f38fe19d25ae5fb7b79abf3df4eea56896 100644 (file)
@@ -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 b046f2b723df834603b7cc0487920fd26f530692..e5b09adf19cdc612d6c6d824e1fad18c30d7ee83 100644 (file)
 
 """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
@@ -41,10 +42,14 @@ QUOTED_STRING = 4
 COMMENT = 5
 DELIMITER = 6
 
+
 class UngetBufferFull(dns.exception.DNSException):
+
     """An attempt was made to unget a token when the unget buffer was full."""
 
+
 class Token(object):
+
     """A DNS master file format token.
 
     @ivar ttype: The token type
@@ -153,7 +158,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
@@ -195,8 +202,12 @@ class Tokenizer(object):
         @type filename: string
         """
 
-        if isinstance(f, (str, unicode)):
-            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:
@@ -255,7 +266,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
 
@@ -279,7 +290,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
@@ -293,7 +304,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():
@@ -350,7 +361,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()
@@ -413,7 +425,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
 
@@ -427,6 +439,8 @@ class Tokenizer(object):
             raise StopIteration
         return token
 
+    __next__ = next
+
     def __iter__(self):
         return self
 
@@ -456,7 +470,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):
@@ -469,7 +484,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):
@@ -486,8 +502,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):
@@ -535,7 +552,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 7c16a9b34f7cfcfa1ec591c2731c3664ce3e19aa..55348528319af93aa623e428f73c06ddb9b54c01 100644 (file)
@@ -23,26 +23,41 @@ import dns.exception
 import dns.hash
 import dns.rdataclass
 import dns.name
+from ._compat import long, string_types
+
 
 class BadTime(dns.exception.DNSException):
+
     """The current time is not within the TSIG's validity time."""
 
+
 class BadSignature(dns.exception.DNSException):
+
     """The TSIG signature fails to verify."""
 
+
 class PeerError(dns.exception.DNSException):
+
     """Base class for all TSIG errors generated by the remote peer"""
 
+
 class PeerBadKey(PeerError):
+
     """The peer didn't know the key we used"""
 
+
 class PeerBadSignature(PeerError):
+
     """The peer didn't like the signature we sent"""
 
+
 class PeerBadTime(PeerError):
+
     """The peer didn't like the time we sent"""
 
+
 class PeerBadTruncation(PeerError):
+
     """The peer didn't like amount of truncation in the TSIG we sent"""
 
 # TSIG Algorithms
@@ -61,6 +76,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):
@@ -86,9 +102,9 @@ def sign(wire, keyname, secret, time, fudge, original_id, error,
         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)
@@ -112,12 +128,14 @@ def sign(wire, keyname, secret, time, fudge, original_id, error,
         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.
@@ -137,13 +155,13 @@ def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
     (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
@@ -171,23 +189,6 @@ def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
         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
@@ -197,24 +198,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.
@@ -223,7 +216,7 @@ def get_algorithm_and_mac(wire, tsig_rdata, tsig_rdlen):
     (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 10de4db5f7837616ca82d1edc183cd02f9202de7..295bac141f2a6b021c40c9bc2c6b3bcd363ec999 100644 (file)
@@ -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 dc92b2146d728ce4f0c85d777b324ac52fe8a3bc..a27d825180274911f82482fe2679a3e195fdb20d 100644 (file)
 """DNS TTL conversion."""
 
 import dns.exception
+from ._compat import long
+
 
 class BadTTL(dns.exception.SyntaxError):
+
     """DNS TTL value is not well-formed."""
 
+
 def from_text(text):
     """Convert the text form of a TTL to an integer.
 
@@ -36,8 +40,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 +49,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 +63,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 8b214721c9352830d25b031ef6c523832307ca83..59728d98251a3873ff0183fefc880816ab5b9e09 100644 (file)
@@ -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,15 +55,15 @@ 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, unicode)):
+        if isinstance(rdclass, string_types):
             rdclass = dns.rdataclass.from_text(rdclass)
         self.zone_rdclass = rdclass
         self.find_rrset(self.question, self.origin, rdclass, dns.rdatatype.SOA,
                         create=True, force_unique=True)
-        if not keyring is None:
+        if keyring is not None:
             self.use_tsig(keyring, keyname, algorithm=keyalgorithm)
 
     def _add_rr(self, name, ttl, rd, deleting=None, section=None):
@@ -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:
@@ -103,7 +107,7 @@ class Update(dns.message.Message):
                     self._add_rr(name, ttl, rd, section=section)
             else:
                 rdtype = args.pop(0)
-                if isinstance(rdtype, (str, unicode)):
+                if isinstance(rdtype, string_types):
                     rdtype = dns.rdatatype.from_text(rdtype)
                 if replace:
                     self.delete(name, rdtype)
@@ -135,12 +139,12 @@ 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,
-                                    dns.rdatatype.ANY, dns.rdatatype.NONE,
-                                    dns.rdatatype.ANY, True, True)
+            self.find_rrset(self.authority, name, dns.rdataclass.ANY,
+                            dns.rdatatype.ANY, dns.rdatatype.NONE,
+                            dns.rdatatype.ANY, True, True)
         elif isinstance(args[0], dns.rdataset.Rdataset):
             for rds in args:
                 for rd in rds:
@@ -152,14 +156,14 @@ 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,
-                                            self.zone_rdclass, rdtype,
-                                            dns.rdatatype.NONE,
-                                            dns.rdataclass.ANY,
-                                            True, True)
+                    self.find_rrset(self.authority, name,
+                                    self.zone_rdclass, rdtype,
+                                    dns.rdatatype.NONE,
+                                    dns.rdataclass.ANY,
+                                    True, True)
                 else:
                     for s in args:
                         rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s,
@@ -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 c3822795510f83c7dfa7e6d2f6894b0761788c1b..8279fef530737302f1cfe9b227b6be40f3791eaf 100644 (file)
@@ -31,4 +31,4 @@ else:
               (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL)
 
 hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \
-             SERIAL
+    SERIAL
index 1d14bd323e7011c1be2e423c063eb5960445e13e..b381f7b928a2f5dde1cd6dab722bac90a79f0f02 100644 (file)
@@ -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 453bbb9c851b990673f7ed8ce57dd6a4af0d1ab4..2b7826c357ade44be5a9fae6f2027f9bfd1ef02a 100644 (file)
@@ -19,6 +19,7 @@ from __future__ import generators
 
 import sys
 import re
+from io import BytesIO
 
 import dns.exception
 import dns.name
@@ -30,25 +31,31 @@ import dns.rrset
 import dns.tokenizer
 import dns.ttl
 import dns.grange
+from ._compat import string_types, text_type
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from io import StringIO
 
 class BadZone(dns.exception.DNSException):
+
     """The DNS zone is malformed."""
 
+
 class NoSOA(BadZone):
+
     """The DNS zone has no SOA RR at its origin."""
 
+
 class NoNS(BadZone):
+
     """The DNS zone has no NS RRset at its origin."""
 
+
 class UnknownOrigin(BadZone):
+
     """The DNS zone's origin is unknown."""
 
+
 class Zone(object):
+
     """A DNS zone.
 
     A Zone is a mapping from names to nodes.  The zone object may be
@@ -110,13 +117,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
@@ -148,12 +156,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)
@@ -208,7 +215,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,
@@ -240,9 +247,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)
@@ -303,12 +310,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)
@@ -366,9 +373,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)
@@ -422,9 +429,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:
@@ -445,9 +452,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:
@@ -474,31 +481,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)
@@ -521,7 +529,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()
@@ -545,6 +553,7 @@ class Zone(object):
 
 
 class _MasterReader(object):
+
     """Read a DNS master file
 
     @ivar tok: The tokenizer
@@ -573,7 +582,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
@@ -597,9 +606,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():
@@ -639,7 +649,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()
@@ -658,7 +669,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()
@@ -760,7 +772,7 @@ class _MasterReader(object):
                 raise dns.exception.SyntaxError
         except:
             raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
-                    token.value)
+                                            token.value)
 
         # lhs (required)
         try:
@@ -768,28 +780,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
@@ -818,7 +828,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()
@@ -836,7 +846,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,
@@ -851,29 +861,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,
@@ -881,29 +893,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.
 
@@ -945,8 +960,9 @@ def from_text(text, origin = None, rdclass = dns.rdataclass.IN,
     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.
 
@@ -976,17 +992,13 @@ def from_file(f, origin = None, rdclass = dns.rdataclass.IN,
     @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:
@@ -1001,6 +1013,7 @@ def from_file(f, origin = None, rdclass = dns.rdataclass.IN,
             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 d9a5f96f54be86cb129f1ba3d5a5efe32f41a980..f284e13c0d6e4ed841143065e6ee78faffd81cd6 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -52,10 +52,7 @@ direct manipulation of DNS zones, messages, names, and records.""",
         "Topic :: Software Development :: Libraries :: Python Modules",
         ],
     'test_suite': 'tests',
+    'provides': ['dns'],
     }
 
-if sys.hexversion >= 0x02050000:
-    kwargs['requires'] = []
-    kwargs['provides'] = ['dns']
-
 setup(**kwargs)
index 5d9d58b51594e28bd562603d3e3c6760fc492590..3d780b477027786a20454aae49ab16758f5be19a 100644 (file)
@@ -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.
 
-from six import BytesIO
+from io import BytesIO
 try:
     import unittest2 as unittest
 except ImportError:
@@ -28,15 +28,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):
@@ -46,7 +46,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):
@@ -58,12 +58,12 @@ class BugsTestCase(unittest.TestCase):
 
     def test_CAA_from_wire(self):
         rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CAA,
-                                    '0 issue "ca.example.net"');
-        f = cStringIO.StringIO()
+                                    u'0 issue "ca.example.net"');
+        f = BytesIO()
         rdata.to_wire(f)
         wire = f.getvalue()
         rdlen = len(wire)
-        wire += "trailing garbage"
+        wire += b"trailing garbage"
         rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.CAA,
                                      wire, 0, rdlen)
         self.failUnless(rdata == rdata2)
index 64e6638ecff8c0490aae25e052d09e4412d0b432..e972a85733239afb3fb6e34529437e7ca198791e 100644 (file)
@@ -233,4 +233,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 d3bb2ee930328e56d57dac2fd0bf1c3996c9d5ee..a72305348188d7087ab3e5f5f0cc839159d86423 100644 (file)
@@ -16,7 +16,6 @@
 import sys
 sys.path.insert(0, '../')  # Force the local project to be *the* dns
 
-import cStringIO
 import filecmp
 import os
 try:
@@ -30,9 +29,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
@@ -136,6 +137,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):
 
@@ -152,7 +156,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,
@@ -190,13 +194,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,
@@ -230,271 +234,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 4ffe26dbe337a03aa54cb115cad718d46b50ca44..c2bbb192219f81a82d3ca14ea5ba60f2bac30147 100644 (file)
@@ -16,7 +16,6 @@
 import sys
 sys.path.insert(0, '../')
 
-import cStringIO
 import filecmp
 import os
 try:
index 8dcdf0ede84bfa0106b64b67f5965bde311cd7f2..795626541f64c79c2a0ef811b7eb73e1e7d771cf 100644 (file)
 # 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
 try:
     import unittest2 as unittest
 except ImportError:
     import unittest
+import binascii
 
 import dns.exception
 import dns.message
+from dns._compat import xrange
 
 query_text = """id 1234
 opcode QUERY
@@ -36,10 +37,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
@@ -69,7 +70,7 @@ goodhex2 = '04d2 8500 0001 0001 0003 0001' \
            '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
@@ -84,10 +85,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):
 
@@ -119,7 +120,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)
@@ -149,13 +150,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 2c00063231316df10b12c8e001dd39dc9e0fedc5..4935564da5d05948f3d08814b150c66ea940428c 100644 (file)
@@ -18,7 +18,7 @@ try:
 except ImportError:
     import unittest
 
-import cStringIO
+from io import BytesIO
 import socket
 
 import dns.name
@@ -31,15 +31,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)
@@ -51,33 +51,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:
@@ -137,7 +137,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')
@@ -200,60 +200,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():
@@ -332,13 +332,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')
@@ -349,12 +349,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():
@@ -364,56 +364,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)
@@ -554,7 +554,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
@@ -573,25 +573,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)
 
@@ -619,48 +619,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.')
@@ -679,15 +679,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'
@@ -697,9 +697,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 bad0917febbf30511dc80751058c00230271810e..043e3d4ecc002996f7912e7e5266d7294e4bc67b 100644 (file)
@@ -17,6 +17,7 @@ try:
     import unittest2 as unittest
 except ImportError:
     import unittest
+import binascii
 
 import dns.exception
 import dns.ipv4
@@ -28,7 +29,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.']
 
@@ -52,8 +53,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():
@@ -72,89 +73,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():
@@ -167,14 +168,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):
@@ -182,6 +183,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):
@@ -197,10 +199,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 e7ad862338dc9cbe3d45fb032227dfbe0c27b24d..fa8339f338a6936bc3229b5216258b10d7f014a9 100644 (file)
@@ -18,13 +18,11 @@ try:
     import unittest2 as unittest
 except ImportError:
     import unittest
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import BytesIO as StringIO
+from io import BytesIO, StringIO
 
 import dns.rrset
 import dns.rdtypes.ANY.EUI48
+import dns.rdtypes.ANY.EUI64
 import dns.exception
 
 
@@ -94,7 +92,7 @@ class RdtypeAnyEUI48TestCase(unittest.TestCase):
         inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
                                            dns.rdatatype.EUI48,
                                            eui)
-        buff = StringIO()
+        buff = BytesIO()
         inst.to_wire(buff)
         self.assertEqual(buff.getvalue(), eui)
 
@@ -193,7 +191,7 @@ class RdtypeAnyEUI64TestCase(unittest.TestCase):
         inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
                                            dns.rdatatype.EUI64,
                                            eui)
-        buff = StringIO()
+        buff = BytesIO()
         inst.to_wire(buff)
         self.assertEqual(buff.getvalue(), eui)
 
index 90e0f15a1d222877b5ceef1f83f842a2b88db8b6..29c39594242c78cc6a9fbc55376ab21f437dc255 100644 (file)
@@ -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
@@ -28,8 +28,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
@@ -58,7 +59,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 d75de3b1afb9122c7ee5350129c2ab51292cc18c..9cd9f76adab94371bb4a9af2b8c81e6fe4ff5e95 100644 (file)
 # 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 3e888ba07567908f031d63b75825daa93f82cefb..95e7175fe11609c55d3d41cd7f6e5b67827c24de 100644 (file)
@@ -17,6 +17,7 @@ try:
     import unittest2 as unittest
 except ImportError:
     import unittest
+import binascii
 
 import dns.update
 import dns.rdata
@@ -37,7 +38,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 e4dd76b49988001e7046be4efff9360f515b6306..9ae23b7c685110efdce7ab6534ff31a2382467d1 100644 (file)
@@ -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
 try:
@@ -28,6 +28,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
@@ -86,8 +89,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.
@@ -98,54 +101,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):
         #
@@ -153,10 +163,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)
@@ -339,7 +349,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,
@@ -364,6 +374,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):
@@ -393,7 +404,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):