r47227 - Merge t-names-authority-py3-8259-3: Port twisted.names.authority to Python 3
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Thu, 14 Apr 2016 04:52:22 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Thu Apr 14 04:52:07 2016
New Revision: 47227
Added:
trunk/twisted/names/topfiles/8259.feature
Modified:
trunk/twisted/names/authority.py
trunk/twisted/names/dns.py
trunk/twisted/names/secondary.py
trunk/twisted/names/test/test_examples.py
trunk/twisted/names/test/test_names.py
trunk/twisted/python/dist3.py
Log:
Merge t-names-authority-py3-8259-3: Port twisted.names.authority to Python 3
Author: pawelmhm, hawkowl
Reviewers: adiroiban, hawkowl, glyph
Fixes: #8259
Modified: trunk/twisted/names/authority.py
==============================================================================
--- trunk/twisted/names/authority.py (original)
+++ trunk/twisted/names/authority.py Thu Apr 14 04:52:07 2016
@@ -6,15 +6,16 @@
Authoritative resolvers.
"""
+from __future__ import absolute_import, division
+
import os
import time
-from twisted.names import dns, error
+from twisted.names import dns, error, common
from twisted.internet import defer
from twisted.python import failure
from twisted.python.compat import execfile
-import common
def getSerial(filename = '/tmp/twisted-names.serial'):
"""Return a monotonically increasing (across program runs) integer.
@@ -24,25 +25,21 @@
"""
serial = time.strftime('%Y%m%d')
- o = os.umask(0177)
+ o = os.umask(0o177)
try:
if not os.path.exists(filename):
- f = file(filename, 'w')
- f.write(serial + ' 0')
- f.close()
+ with open(filename, 'w') as f:
+ f.write(serial + ' 0')
finally:
os.umask(o)
- serialFile = file(filename, 'r')
- lastSerial, ID = serialFile.readline().split()
+ with open(filename, 'r') as serialFile:
+ lastSerial, ID = serialFile.readline().split()
+
ID = (lastSerial == serial) and (int(ID) + 1) or 0
- serialFile.close()
- serialFile = file(filename, 'w')
- serialFile.write('%s %d' % (serial, ID))
- serialFile.close()
- serial = serial + ('%02d' % (ID,))
- return serial
+ with open(filename, 'w') as serialFile:
+ serialFile.write('%s %d' % (serial, ID))
#class LookupCacherMixin(object):
# _cache = None
@@ -58,6 +55,8 @@
# r = self._meth(name, cls, type, timeout)
# self._cache[(name, cls, type)] = r
# return r
+ serial = serial + ('%02d' % (ID,))
+ return serial
@@ -67,8 +66,12 @@
@ivar _ADDITIONAL_PROCESSING_TYPES: Record types for which additional
processing will be done.
+
@ivar _ADDRESS_TYPES: Record types which are useful for inclusion in the
additional section generated during additional processing.
+
+ @ivar soa: A 2-tuple containing the SOA domain name as a L{bytes} and a
+ L{dns.Record_SOA}.
"""
# See https://twistedmatrix.com/trac/ticket/6650
_ADDITIONAL_PROCESSING_TYPES = (dns.CNAME, dns.MX, dns.NS)
@@ -244,7 +247,7 @@
g, l = self.setupConfigNamespace(), {}
execfile(filename, g, l)
if not l.has_key('zone'):
- raise ValueError, "No zone defined in " + filename
+ raise ValueError("No zone defined in " + filename)
self.records = {}
for rr in l['zone']:
@@ -272,7 +275,9 @@
def loadFile(self, filename):
self.origin = os.path.basename(filename) + '.' # XXX - this might suck
- lines = open(filename).readlines()
+
+ with open(filename, 'rb') as f:
+ lines = f.readlines()
lines = self.stripComments(lines)
lines = self.collapseContinuations(lines)
self.parseLines(lines)
@@ -337,7 +342,7 @@
if f:
f(ttl, type, domain, rdata)
else:
- raise NotImplementedError, "Record class %r not supported" % cls
+ raise NotImplementedError("Record class %r not supported" % cls)
def class_IN(self, ttl, type, domain, rdata):
@@ -347,11 +352,11 @@
r.ttl = ttl
self.records.setdefault(domain.lower(), []).append(r)
- print 'Adding IN Record', domain, ttl, r
+ print('Adding IN Record', domain, ttl, r)
if type == 'SOA':
self.soa = (domain, r)
else:
- raise NotImplementedError, "Record type %r not supported" % type
+ raise NotImplementedError("Record type %r not supported" % type)
#
Modified: trunk/twisted/names/dns.py
==============================================================================
--- trunk/twisted/names/dns.py (original)
+++ trunk/twisted/names/dns.py Thu Apr 14 04:52:07 2016
@@ -69,8 +69,8 @@
Construct a bytes object representing a single byte with the given
ordinal value.
- @type ordinal: C{int}
- @rtype: C{bytes}
+ @type ordinal: L{int}
+ @rtype: L{bytes}
"""
return bytes([ordinal])
@@ -81,7 +81,7 @@
to an end user.
@param bytes: The bytes to represent.
- @rtype: C{str}
+ @rtype: L{str}
"""
return repr(bytes)[1:]
@@ -92,7 +92,7 @@
presentation to an end user.
@param list: The list of bytes to represent.
- @rtype: C{str}
+ @rtype: L{str}
"""
return '[%s]' % (
', '.join([_nicebytes(b) for b in list]),)
@@ -212,7 +212,7 @@
"""
Split a domain name into its constituent labels.
- @type name: C{str}
+ @type name: L{bytes}
@param name: A fully qualified domain name (with or without a
trailing dot).
@@ -244,10 +244,10 @@
C{descendantName} is considered a I{subdomain} if its sequence of
labels ends with the labels of C{ancestorName}.
- @type descendantName: C{bytes}
+ @type descendantName: L{bytes}
@param descendantName: The DNS subdomain name.
- @type ancestorName: C{bytes}
+ @type ancestorName: L{bytes}
@param ancestorName: The DNS parent or ancestor domain name.
@return: C{True} if C{descendantName} is equal to or if it is a
@@ -270,15 +270,19 @@
(years). For example: C{"3S"} indicates an interval of three seconds;
C{"5D"} indicates an interval of five days. Alternatively, C{s} may be
any non-string and it will be returned unmodified.
- @type s: text string (C{str}) for parsing; anything else for passthrough.
+ @type s: text string (L{bytes} or L{unicode}) for parsing; anything else
+ for passthrough.
- @return: an C{int} giving the interval represented by the string C{s}, or
+ @return: an L{int} giving the interval represented by the string C{s}, or
whatever C{s} is if it is not a string.
"""
suffixes = (
('S', 1), ('M', 60), ('H', 60 * 60), ('D', 60 * 60 * 24),
('W', 60 * 60 * 24 * 7), ('Y', 60 * 60 * 24 * 365)
)
+ if _PY3 and isinstance(s, bytes):
+ s = s.decode('ascii')
+
if isinstance(s, str):
s = s.upper().strip()
for (suff, mult) in suffixes:
@@ -326,7 +330,7 @@
@type strio: File-like object
@param strio: The stream from which bytes may be read
- @type length: C{int} or C{None}
+ @type length: L{int} or L{None}
@param length: The number of bytes in this RDATA field. Most
implementations can ignore this value. Only in the case of
records similar to TXT where the total length is in no way
@@ -405,9 +409,13 @@
I{twistedmatrix.com}.
@ivar name: A byte string giving the name.
- @type name: C{bytes}
+ @type name: L{bytes}
"""
def __init__(self, name=b''):
+ """
+ @param name: A name.
+ @type name: L{unicode} or L{bytes}
+ """
if isinstance(name, unicode):
name = name.encode('idna')
if not isinstance(name, bytes):
@@ -520,8 +528,13 @@
Represent a single DNS query.
@ivar name: The name about which this query is requesting information.
+ @type name: L{Name}
+
@ivar type: The query type.
+ @type type: L{int}
+
@ivar cls: The query class.
+ @type cls: L{int}
"""
name = None
type = None
@@ -529,13 +542,13 @@
def __init__(self, name=b'', type=A, cls=IN):
"""
- @type name: C{bytes}
- @param name: The name about which to request information.
+ @type name: L{bytes} or L{unicode}
+ @param name: See L{Query.name}
- @type type: C{int}
+ @type type: L{int}
@param type: The query type.
- @type cls: C{int}
+ @type cls: L{int}
@param cls: The query class.
"""
self.name = Name(name)
@@ -823,16 +836,23 @@
"""
A resource record header.
- @cvar fmt: C{str} specifying the byte format of an RR.
+ @cvar fmt: L{str} specifying the byte format of an RR.
@ivar name: The name about which this reply contains information.
+ @type name: L{Name}
+
@ivar type: The query type of the original request.
+ @type type: L{int}
+
@ivar cls: The query class of the original request.
+
@ivar ttl: The time-to-live for this record.
- @ivar payload: An object that implements the IEncodable interface
+ @type ttl: L{int}
+
+ @ivar payload: An object that implements the L{IEncodable} interface
- @ivar auth: A C{bool} indicating whether this C{RRHeader} was parsed from an
- authoritative message.
+ @ivar auth: A L{bool} indicating whether this C{RRHeader} was parsed from
+ an authoritative message.
"""
compareAttributes = ('name', 'type', 'cls', 'ttl', 'payload', 'auth')
@@ -847,18 +867,19 @@
cachedResponse = None
- def __init__(self, name=b'', type=A, cls=IN, ttl=0, payload=None, auth=False):
+ def __init__(self, name=b'', type=A, cls=IN, ttl=0, payload=None,
+ auth=False):
"""
- @type name: C{bytes}
- @param name: The name about which this reply contains information.
+ @type name: L{bytes} or L{unicode}
+ @param name: See L{RRHeader.name}
- @type type: C{int}
+ @type type: L{int}
@param type: The query type.
- @type cls: C{int}
+ @type cls: L{int}
@param cls: The query class.
- @type ttl: C{int}
+ @type ttl: L{int}
@param ttl: Time to live for this record.
@type payload: An object implementing C{IEncodable}
@@ -921,7 +942,7 @@
@type name: L{Name}
@ivar name: The name associated with this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -932,6 +953,10 @@
name = None
def __init__(self, name=b'', ttl=None):
+ """
+ @param name: See L{SimpleRecord.name}
+ @type name: L{bytes} or L{unicode}
+ """
self.name = Name(name)
self.ttl = str2time(ttl)
@@ -1057,11 +1082,11 @@
"""
An IPv4 host address.
- @type address: C{str}
+ @type address: L{bytes}
@ivar address: The packed network-order representation of the IPv4 address
associated with this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1071,6 +1096,14 @@
address = None
def __init__(self, address='0.0.0.0', ttl=None):
+ """
+ @type address: L{bytes} or L{unicode}
+ @param address: The IPv4 address associated with this record, in
+ quad-dotted notation.
+ """
+ if _PY3 and isinstance(address, bytes):
+ address = address.decode('idna')
+
address = socket.inet_aton(address)
self.address = address
self.ttl = str2time(ttl)
@@ -1114,28 +1147,28 @@
@ivar rname: A domain-name which specifies the mailbox of the person
responsible for this zone.
- @type serial: C{int}
+ @type serial: L{int}
@ivar serial: The unsigned 32 bit version number of the original copy of
the zone. Zone transfers preserve this value. This value wraps and
should be compared using sequence space arithmetic.
- @type refresh: C{int}
+ @type refresh: L{int}
@ivar refresh: A 32 bit time interval before the zone should be refreshed.
- @type minimum: C{int}
+ @type minimum: L{int}
@ivar minimum: The unsigned 32 bit minimum TTL field that should be
exported with any RR from this zone.
- @type expire: C{int}
+ @type expire: L{int}
@ivar expire: A 32 bit time value that specifies the upper limit on the
time interval that can elapse before the zone is no longer
authoritative.
- @type retry: C{int}
+ @type retry: L{int}
@ivar retry: A 32 bit time interval that should elapse before a failed
refresh should be retried.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The default TTL to use for records served from this zone.
"""
fancybasename = 'SOA'
@@ -1146,6 +1179,13 @@
def __init__(self, mname=b'', rname=b'', serial=0, refresh=0, retry=0,
expire=0, minimum=0, ttl=None):
+ """
+ @param mname: See L{Record_SOA.mname}
+ @type mname: L{bytes} or L{unicode}
+
+ @param rname: See L{Record_SOA.rname}
+ @type rname: L{bytes} or L{unicode}
+ """
self.mname, self.rname = Name(mname), Name(rname)
self.serial, self.refresh = str2time(serial), str2time(refresh)
self.minimum, self.expire = str2time(minimum), str2time(expire)
@@ -1188,7 +1228,7 @@
This is an experimental record type.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1223,19 +1263,19 @@
This record type is obsolete. See L{Record_SRV}.
- @type address: C{str}
+ @type address: L{bytes}
@ivar address: The packed network-order representation of the IPv4 address
associated with this record.
- @type protocol: C{int}
+ @type protocol: L{int}
@ivar protocol: The 8 bit IP protocol number for which this service map is
relevant.
- @type map: C{str}
+ @type map: L{bytes}
@ivar map: A bitvector indicating the services available at the specified
address.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1247,7 +1287,15 @@
_address = property(lambda self: socket.inet_ntoa(self.address))
- def __init__(self, address='0.0.0.0', protocol=0, map='', ttl=None):
+ def __init__(self, address='0.0.0.0', protocol=0, map=b'', ttl=None):
+ """
+ @type address: L{bytes} or L{unicode}
+ @param address: The IPv4 address associated with this record, in
+ quad-dotted notation.
+ """
+ if _PY3 and isinstance(address, bytes):
+ address = address.decode('idna')
+
self.address = socket.inet_aton(address)
self.protocol, self.map = protocol, map
self.ttl = str2time(ttl)
@@ -1275,11 +1323,11 @@
"""
An IPv6 host address.
- @type address: C{str}
+ @type address: L{bytes}
@ivar address: The packed network-order representation of the IPv6 address
associated with this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1294,6 +1342,13 @@
_address = property(lambda self: socket.inet_ntop(AF_INET6, self.address))
def __init__(self, address='::', ttl=None):
+ """
+ @type address: L{bytes} or L{unicode}
+ @param address: The IPv6 address for this host, in RFC 2373 format.
+ """
+ if _PY3 and isinstance(address, bytes):
+ address = address.decode('idna')
+
self.address = socket.inet_pton(AF_INET6, address)
self.ttl = str2time(ttl)
@@ -1318,20 +1373,20 @@
This is an experimental record type.
- @type prefixLen: C{int}
+ @type prefixLen: L{int}
@ivar prefixLen: The length of the suffix.
- @type suffix: C{str}
+ @type suffix: L{bytes}
@ivar suffix: An IPv6 address suffix in network order.
@type prefix: L{Name}
@ivar prefix: If specified, a name which will be used as a prefix for other
A6 records.
- @type bytes: C{int}
+ @type bytes: L{int}
@ivar bytes: The length of the prefix.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1348,6 +1403,16 @@
_suffix = property(lambda self: socket.inet_ntop(AF_INET6, self.suffix))
def __init__(self, prefixLen=0, suffix='::', prefix=b'', ttl=None):
+ """
+ @param suffix: An IPv6 address suffix in in RFC 2373 format.
+ @type suffix: L{bytes} or L{unicode}
+
+ @param prefix: An IPv6 address prefix for other A6 records.
+ @type prefix: L{bytes} or L{unicode}
+ """
+ if _PY3 and isinstance(suffix, bytes):
+ suffix = suffix.decode('idna')
+
self.prefixLen = prefixLen
self.suffix = socket.inet_pton(AF_INET6, suffix)
self.prefix = Name(prefix)
@@ -1402,18 +1467,18 @@
This is an experimental record type.
- @type priority: C{int}
+ @type priority: L{int}
@ivar priority: The priority of this target host. A client MUST attempt to
contact the target host with the lowest-numbered priority it can reach;
target hosts with the same priority SHOULD be tried in an order defined
by the weight field.
- @type weight: C{int}
+ @type weight: L{int}
@ivar weight: Specifies a relative weight for entries with the same
priority. Larger weights SHOULD be given a proportionately higher
probability of being selected.
- @type port: C{int}
+ @type port: L{int}
@ivar port: The port on this target host of this service.
@type target: L{Name}
@@ -1424,7 +1489,7 @@
section. Unless and until permitted by future standards action, name
compression is not to be used for this field.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1437,6 +1502,10 @@
showAttributes = ('priority', 'weight', ('target', 'target', '%s'), 'port', 'ttl')
def __init__(self, priority=0, weight=0, port=0, target=b'', ttl=None):
+ """
+ @param target: See L{Record_SRV.target}
+ @type target: L{bytes} or L{unicode}
+ """
self.priority = int(priority)
self.weight = int(weight)
self.port = int(port)
@@ -1467,12 +1536,12 @@
"""
The location of the server(s) for a specific protocol and domain.
- @type order: C{int}
+ @type order: L{int}
@ivar order: An integer specifying the order in which the NAPTR records
MUST be processed to ensure the correct ordering of rules. Low numbers
are processed before high numbers.
- @type preference: C{int}
+ @type preference: L{int}
@ivar preference: An integer that specifies the order in which NAPTR
records with equal "order" values SHOULD be processed, low numbers
being processed before high numbers.
@@ -1501,7 +1570,7 @@
records depending on the value of the flags field. This MUST be a
fully qualified domain-name.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1517,8 +1586,12 @@
('service', 'service', '%s'), ('regexp', 'regexp', '%s'),
('replacement', 'replacement', '%s'), 'ttl')
- def __init__(self, order=0, preference=0, flags=b'', service=b'', regexp=b'',
- replacement=b'', ttl=None):
+ def __init__(self, order=0, preference=0, flags=b'', service=b'',
+ regexp=b'', replacement=b'', ttl=None):
+ """
+ @param replacement: See L{Record_NAPTR.replacement}
+ @type replacement: L{bytes} or L{unicode}
+ """
self.order = int(order)
self.preference = int(preference)
self.flags = Charstr(flags)
@@ -1562,7 +1635,7 @@
"""
Map from a domain name to the name of an AFS cell database server.
- @type subtype: C{int}
+ @type subtype: L{int}
@ivar subtype: In the case of subtype 1, the host has an AFS version 3.0
Volume Location Server for the named AFS cell. In the case of subtype
2, the host has an authenticated name server holding the cell-root
@@ -1572,7 +1645,7 @@
@ivar hostname: The domain name of a host that has a server for the cell
named by this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1585,6 +1658,10 @@
showAttributes = ('subtype', ('hostname', 'hostname', '%s'), 'ttl')
def __init__(self, subtype=0, hostname=b'', ttl=None):
+ """
+ @param hostname: See L{Record_AFSDB.hostname}
+ @type hostname: L{bytes} or L{unicode}
+ """
self.subtype = int(subtype)
self.hostname = Name(hostname)
self.ttl = str2time(ttl)
@@ -1619,7 +1696,7 @@
@ivar txt: A domain name for which TXT RR's exist (indirection through
which allows information sharing about the contents of this RP record).
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
@@ -1632,6 +1709,13 @@
showAttributes = (('mbox', 'mbox', '%s'), ('txt', 'txt', '%s'), 'ttl')
def __init__(self, mbox=b'', txt=b'', ttl=None):
+ """
+ @param mbox: See L{Record_RP.mbox}.
+ @type mbox: L{bytes} or L{unicode}
+
+ @param txt: See L{Record_RP.txt}
+ @type txt: L{bytes} or L{unicode}
+ """
self.mbox = Name(mbox)
self.txt = Name(txt)
self.ttl = str2time(ttl)
@@ -1659,13 +1743,13 @@
"""
Host information.
- @type cpu: C{str}
+ @type cpu: L{bytes}
@ivar cpu: Specifies the CPU type.
- @type os: C{str}
+ @type os: L{bytes}
@ivar os: Specifies the OS.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1675,7 +1759,7 @@
showAttributes = (('cpu', _nicebytes), ('os', _nicebytes), 'ttl')
compareAttributes = ('cpu', 'os', 'ttl')
- def __init__(self, cpu='', os='', ttl=None):
+ def __init__(self, cpu=b'', os=b'', ttl=None):
self.cpu, self.os = cpu, os
self.ttl = str2time(ttl)
@@ -1723,7 +1807,7 @@
owner of the MINFO record. If this domain name names the root, errors
should be returned to the sender of the message.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1739,6 +1823,13 @@
'ttl')
def __init__(self, rmailbx=b'', emailbx=b'', ttl=None):
+ """
+ @param rmailbx: See L{Record_MINFO.rmailbx}.
+ @type rmailbx: L{bytes} or L{unicode}
+
+ @param emailbx: See L{Record_MINFO.rmailbx}.
+ @type emailbx: L{bytes} or L{unicode}
+ """
self.rmailbx, self.emailbx = Name(rmailbx), Name(emailbx)
self.ttl = str2time(ttl)
@@ -1764,7 +1855,7 @@
"""
Mail exchange.
- @type preference: C{int}
+ @type preference: L{int}
@ivar preference: Specifies the preference given to this RR among others at
the same owner. Lower values are preferred.
@@ -1772,7 +1863,7 @@
@ivar name: A domain-name which specifies a host willing to act as a mail
exchange.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be
cached.
"""
@@ -1783,7 +1874,12 @@
showAttributes = ('preference', ('name', 'name', '%s'), 'ttl')
def __init__(self, preference=0, name=b'', ttl=None, **kwargs):
- self.preference, self.name = int(preference), Name(kwargs.get('exchange', name))
+ """
+ @param name: See L{Record_MX.name}.
+ @type name: L{bytes} or L{unicode}
+ """
+ self.preference = int(preference)
+ self.name = Name(kwargs.get('exchange', name))
self.ttl = str2time(ttl)
def encode(self, strio, compDict = None):
@@ -1806,10 +1902,10 @@
"""
Freeform text.
- @type data: C{list} of C{bytes}
+ @type data: L{list} of L{bytes}
@ivar data: Freeform text which makes up this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be cached.
"""
TYPE = TXT
@@ -1855,10 +1951,10 @@
Encapsulate the wire data for unknown record types so that they can
pass through the system unchanged.
- @type data: C{bytes}
+ @type data: L{bytes}
@ivar data: Wire data which makes up this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be cached.
@since: 11.1
@@ -1900,10 +1996,10 @@
Structurally, freeform text. Semantically, a policy definition, formatted
as defined in U{rfc 4408<http://www.faqs.org/rfcs/rfc4408.html>}.
- @type data: C{list} of C{str}
+ @type data: L{list} of L{bytes}
@ivar data: Freeform text which makes up this record.
- @type ttl: C{int}
+ @type ttl: L{int}
@ivar ttl: The maximum number of seconds which this record should be cached.
"""
TYPE = SPF
@@ -2158,13 +2254,13 @@
"""
Add another query to this Message.
- @type name: C{bytes}
+ @type name: L{bytes}
@param name: The name to query.
- @type type: C{int}
+ @type type: L{int}
@param type: Query type
- @type cls: C{int}
+ @type cls: L{int}
@param cls: Query class
"""
self.queries.append(Query(name, type, cls))
@@ -2272,9 +2368,9 @@
Retrieve the L{IRecord} implementation for the given record type.
@param type: A record type, such as L{A} or L{NS}.
- @type type: C{int}
+ @type type: L{int}
- @return: An object which implements L{IRecord} or C{None} if none
+ @return: An object which implements L{IRecord} or L{None} if none
can be found for the given type.
@rtype: L{types.ClassType}
"""
@@ -2286,7 +2382,7 @@
Encode this L{Message} into a byte string in the format described by RFC
1035.
- @rtype: C{bytes}
+ @rtype: L{bytes}
"""
strio = BytesIO()
self.encode(strio)
@@ -2413,7 +2509,7 @@
@param dnssecOK: DNSSEC OK bit as defined by
U{RFC3225 3<https://tools.ietf.org/html/rfc3225#section-3>}.
- @type dnssecOK: C{bool}
+ @type dnssecOK: L{bool}
@param authenticData: A flag indicating in a response that all the data
included in the answer and authority portion of the response has
@@ -2656,13 +2752,13 @@
"""
Send out a message with the given queries.
- @type queries: C{list} of C{Query} instances
+ @type queries: L{list} of C{Query} instances
@param queries: The queries to transmit
- @type timeout: C{int} or C{float}
+ @type timeout: L{int} or C{float}
@param timeout: How long to wait before giving up
- @type id: C{int}
+ @type id: L{int}
@param id: Unique key for this request
@type writeMessage: C{callable}
@@ -2776,10 +2872,10 @@
"""
Send out a message with the given queries.
- @type address: C{tuple} of C{str} and C{int}
+ @type address: L{tuple} of L{str} and L{int}
@param address: The address to which to send the query
- @type queries: C{list} of C{Query} instances
+ @type queries: L{list} of C{Query} instances
@param queries: The queries to transmit
@rtype: C{Deferred}
@@ -2870,7 +2966,7 @@
"""
Send out a message with the given queries.
- @type queries: C{list} of C{Query} instances
+ @type queries: L{list} of C{Query} instances
@param queries: The queries to transmit
@rtype: C{Deferred}
Modified: trunk/twisted/names/secondary.py
==============================================================================
--- trunk/twisted/names/secondary.py (original)
+++ trunk/twisted/names/secondary.py Thu Apr 14 04:52:07 2016
@@ -2,6 +2,8 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
+from __future__ import absolute_import, division
+
__all__ = ['SecondaryAuthority', 'SecondaryAuthorityService']
from twisted.internet import task, defer
@@ -23,9 +25,11 @@
"""
@param primary: The IP address of the server from which to perform
zone transfers.
+ @type primary: L{str}
@param domains: A sequence of domain names for which to perform
zone transfers.
+ @type domains: L{list} of L{bytes}
"""
self.primary = primary
self.domains = [SecondaryAuthority(primary, d) for d in domains]
@@ -43,7 +47,7 @@
C{int} giving a port number. Together, these define where zone
transfers will be attempted from.
- @param domain: A C{str} giving the domain to transfer.
+ @param domain: A C{bytes} giving the domain to transfer.
@return: A new instance of L{SecondaryAuthorityService}.
"""
@@ -98,6 +102,11 @@
_reactor = None
def __init__(self, primaryIP, domain):
+ """
+ @param domain: The domain for which this will be the secondary
+ authority.
+ @type domain: L{bytes}
+ """
# Yep. Skip over FileAuthority.__init__. This is a hack until we have
# a good composition-based API for the complicated DNS record lookup
# logic we want to share.
@@ -110,7 +119,7 @@
def fromServerAddressAndDomain(cls, serverAddress, domain):
"""
Construct a new L{SecondaryAuthority} from a tuple giving a server
- address and a C{str} giving the name of a domain for which this is an
+ address and a C{bytes} giving the name of a domain for which this is an
authority.
@param serverAddress: A two-tuple, the first element of which is a
@@ -118,7 +127,7 @@
C{int} giving a port number. Together, these define where zone
transfers will be attempted from.
- @param domain: A C{str} giving the domain to transfer.
+ @param domain: A C{bytes} giving the domain to transfer.
@return: A new instance of L{SecondaryAuthority}.
"""
Modified: trunk/twisted/names/test/test_examples.py
==============================================================================
--- trunk/twisted/names/test/test_examples.py (original)
+++ trunk/twisted/names/test/test_examples.py Thu Apr 14 04:52:07 2016
@@ -5,12 +5,13 @@
Tests for L{twisted.names} example scripts.
"""
+from __future__ import absolute_import, division
+
import sys
-from StringIO import StringIO
from twisted.python.filepath import FilePath
from twisted.trial.unittest import SkipTest, TestCase
-
+from twisted.python.compat import NativeStringIO
class ExampleTestBase(object):
@@ -37,9 +38,10 @@
self.originalPath = sys.path[:]
self.originalModules = sys.modules.copy()
- self.fakeErr = StringIO()
+ # Python usually expects native strs to be written to sys.stdout/stderr
+ self.fakeErr = NativeStringIO()
self.patch(sys, 'stderr', self.fakeErr)
- self.fakeOut = StringIO()
+ self.fakeOut = NativeStringIO()
self.patch(sys, 'stdout', self.fakeOut)
# Get documentation root
@@ -81,7 +83,7 @@
"""
self.assertEqual(
self.examplePath.open().readline().rstrip(),
- '#!/usr/bin/env python')
+ b'#!/usr/bin/env python')
def test_usageConsistency(self):
Modified: trunk/twisted/names/test/test_names.py
==============================================================================
--- trunk/twisted/names/test/test_names.py (original)
+++ trunk/twisted/names/test/test_names.py Thu Apr 14 04:52:07 2016
@@ -5,8 +5,13 @@
Test cases for twisted.names.
"""
-import socket, operator, copy
-from StringIO import StringIO
+from __future__ import absolute_import, division
+
+import socket
+import operator
+import copy
+
+from io import BytesIO
from functools import partial, reduce
from struct import pack
@@ -34,8 +39,8 @@
soa_record = dns.Record_SOA(
- mname = 'test-domain.com',
- rname = 'root.test-domain.com',
+ mname = b'test-domain.com',
+ rname = u'root.test-domain.com',
serial = 100,
refresh = 1234,
minimum = 7654,
@@ -45,8 +50,8 @@
)
reverse_soa = dns.Record_SOA(
- mname = '93.84.28.in-addr.arpa',
- rname = '93.84.28.in-addr.arpa',
+ mname = b'93.84.28.in-addr.arpa',
+ rname = b'93.84.28.in-addr.arpa',
serial = 120,
refresh = 54321,
minimum = 382,
@@ -56,8 +61,8 @@
)
my_soa = dns.Record_SOA(
- mname = 'my-domain.com',
- rname = 'postmaster.test-domain.com',
+ mname = u'my-domain.com',
+ rname = b'postmaster.test-domain.com',
serial = 130,
refresh = 12345,
minimum = 1,
@@ -66,61 +71,63 @@
)
test_domain_com = NoFileAuthority(
- soa = ('test-domain.com', soa_record),
+ soa = (b'test-domain.com', soa_record),
records = {
- 'test-domain.com': [
+ b'test-domain.com': [
soa_record,
- dns.Record_A('127.0.0.1'),
- dns.Record_NS('39.28.189.39'),
- dns.Record_SPF('v=spf1 mx/30 mx:example.org/30 -all'),
- dns.Record_SPF('v=spf1 +mx a:\0colo', '.example.com/28 -all not valid'),
- dns.Record_MX(10, 'host.test-domain.com'),
- dns.Record_HINFO(os='Linux', cpu='A Fast One, Dontcha know'),
- dns.Record_CNAME('canonical.name.com'),
- dns.Record_MB('mailbox.test-domain.com'),
- dns.Record_MG('mail.group.someplace'),
- dns.Record_TXT('A First piece of Text', 'a SecoNd piece'),
- dns.Record_A6(0, 'ABCD::4321', ''),
- dns.Record_A6(12, '0:0069::0', 'some.network.tld'),
- dns.Record_A6(8, '0:5634:1294:AFCB:56AC:48EF:34C3:01FF', 'tra.la.la.net'),
- dns.Record_TXT('Some more text, haha! Yes. \0 Still here?'),
- dns.Record_MR('mail.redirect.or.whatever'),
- dns.Record_MINFO(rmailbx='r mail box', emailbx='e mail box'),
- dns.Record_AFSDB(subtype=1, hostname='afsdb.test-domain.com'),
- dns.Record_RP(mbox='whatever.i.dunno', txt='some.more.text'),
- dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP,
- '\x12\x01\x16\xfe\xc1\x00\x01'),
- dns.Record_NAPTR(100, 10, "u", "sip+E2U",
- "!^.*$!sip:[email protected]!"),
- dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF')],
- 'http.tcp.test-domain.com': [
- dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool')
+ dns.Record_A(b'127.0.0.1'),
+ dns.Record_NS(b'39.28.189.39'),
+ dns.Record_SPF(b'v=spf1 mx/30 mx:example.org/30 -all'),
+ dns.Record_SPF(b'v=spf1 +mx a:\0colo',
+ b'.example.com/28 -all not valid'),
+ dns.Record_MX(10, u'host.test-domain.com'),
+ dns.Record_HINFO(os=b'Linux', cpu=b'A Fast One, Dontcha know'),
+ dns.Record_CNAME(b'canonical.name.com'),
+ dns.Record_MB(b'mailbox.test-domain.com'),
+ dns.Record_MG(b'mail.group.someplace'),
+ dns.Record_TXT(b'A First piece of Text', b'a SecoNd piece'),
+ dns.Record_A6(0, b'ABCD::4321', b''),
+ dns.Record_A6(12, b'0:0069::0', b'some.network.tld'),
+ dns.Record_A6(8, b'0:5634:1294:AFCB:56AC:48EF:34C3:01FF',
+ b'tra.la.la.net'),
+ dns.Record_TXT(b'Some more text, haha! Yes. \0 Still here?'),
+ dns.Record_MR(b'mail.redirect.or.whatever'),
+ dns.Record_MINFO(rmailbx=b'r mail box', emailbx=b'e mail box'),
+ dns.Record_AFSDB(subtype=1, hostname=b'afsdb.test-domain.com'),
+ dns.Record_RP(mbox=b'whatever.i.dunno', txt=b'some.more.text'),
+ dns.Record_WKS(b'12.54.78.12', socket.IPPROTO_TCP,
+ b'\x12\x01\x16\xfe\xc1\x00\x01'),
+ dns.Record_NAPTR(100, 10, b"u", b"sip+E2U",
+ b"!^.*$!sip:[email protected]!"),
+ dns.Record_AAAA(b'AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF')],
+ b'http.tcp.test-domain.com': [
+ dns.Record_SRV(257, 16383, 43690, b'some.other.place.fool')
],
- 'host.test-domain.com': [
- dns.Record_A('123.242.1.5'),
- dns.Record_A('0.255.0.255'),
+ b'host.test-domain.com': [
+ dns.Record_A(b'123.242.1.5'),
+ dns.Record_A(b'0.255.0.255'),
],
- 'host-two.test-domain.com': [
+ b'host-two.test-domain.com': [
#
# Python bug
# dns.Record_A('255.255.255.255'),
#
- dns.Record_A('255.255.255.254'),
- dns.Record_A('0.0.0.0')
+ dns.Record_A(b'255.255.255.254'),
+ dns.Record_A(b'0.0.0.0')
],
- 'cname.test-domain.com': [
- dns.Record_CNAME('test-domain.com')
+ b'cname.test-domain.com': [
+ dns.Record_CNAME(b'test-domain.com')
],
- 'anothertest-domain.com': [
- dns.Record_A('1.2.3.4')],
+ b'anothertest-domain.com': [
+ dns.Record_A(b'1.2.3.4')],
}
)
reverse_domain = NoFileAuthority(
- soa = ('93.84.28.in-addr.arpa', reverse_soa),
+ soa = (b'93.84.28.in-addr.arpa', reverse_soa),
records = {
- '123.93.84.28.in-addr.arpa': [
- dns.Record_PTR('test.host-reverse.lookup.com'),
+ b'123.93.84.28.in-addr.arpa': [
+ dns.Record_PTR(b'test.host-reverse.lookup.com'),
reverse_soa
]
}
@@ -128,14 +135,15 @@
my_domain_com = NoFileAuthority(
- soa = ('my-domain.com', my_soa),
+ soa = (b'my-domain.com', my_soa),
records = {
- 'my-domain.com': [
+ b'my-domain.com': [
my_soa,
- dns.Record_A('1.2.3.4', ttl='1S'),
- dns.Record_NS('ns1.domain', ttl='2M'),
- dns.Record_NS('ns2.domain', ttl='3H'),
- dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', ttl='4D')
+ dns.Record_A(b'1.2.3.4', ttl='1S'),
+ dns.Record_NS(b'ns1.domain', ttl=b'2M'),
+ dns.Record_NS(b'ns2.domain', ttl='3H'),
+ dns.Record_SRV(257, 16383, 43690, b'some.other.place.fool',
+ ttl='4D')
]
}
)
@@ -224,7 +232,8 @@
"""Test DNS 'A' record queries with multiple answers"""
return self.namesTest(
self.resolver.lookupAddress('host.test-domain.com'),
- [dns.Record_A('123.242.1.5', ttl=19283784), dns.Record_A('0.255.0.255', ttl=19283784)]
+ [dns.Record_A('123.242.1.5', ttl=19283784),
+ dns.Record_A('0.255.0.255', ttl=19283784)]
)
@@ -268,7 +277,8 @@
"""Test DNS 'HINFO' record queries"""
return self.namesTest(
self.resolver.lookupHostInfo('test-domain.com'),
- [dns.Record_HINFO(os='Linux', cpu='A Fast One, Dontcha know', ttl=19283784)]
+ [dns.Record_HINFO(os=b'Linux', cpu=b'A Fast One, Dontcha know',
+ ttl=19283784)]
)
def test_PTR(self):
@@ -345,8 +355,10 @@
"""Test DNS 'TXT' record queries"""
return self.namesTest(
self.resolver.lookupText('test-domain.com'),
- [dns.Record_TXT('A First piece of Text', 'a SecoNd piece', ttl=19283784),
- dns.Record_TXT('Some more text, haha! Yes. \0 Still here?', ttl=19283784)]
+ [dns.Record_TXT(b'A First piece of Text', b'a SecoNd piece',
+ ttl=19283784),
+ dns.Record_TXT(b'Some more text, haha! Yes. \0 Still here?',
+ ttl=19283784)]
)
@@ -356,8 +368,10 @@
"""
return self.namesTest(
self.resolver.lookupSenderPolicy('test-domain.com'),
- [dns.Record_SPF('v=spf1 mx/30 mx:example.org/30 -all', ttl=19283784),
- dns.Record_SPF('v=spf1 +mx a:\0colo', '.example.com/28 -all not valid', ttl=19283784)]
+ [dns.Record_SPF(b'v=spf1 mx/30 mx:example.org/30 -all',
+ ttl=19283784),
+ dns.Record_SPF(b'v=spf1 +mx a:\0colo',
+ b'.example.com/28 -all not valid', ttl=19283784)]
)
@@ -365,7 +379,8 @@
"""Test DNS 'WKS' record queries"""
return self.namesTest(
self.resolver.lookupWellKnownServices('test-domain.com'),
- [dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP, '\x12\x01\x16\xfe\xc1\x00\x01', ttl=19283784)]
+ [dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP,
+ b'\x12\x01\x16\xfe\xc1\x00\x01', ttl=19283784)]
)
@@ -428,8 +443,8 @@
"""
return self.namesTest(
self.resolver.lookupNamingAuthorityPointer('test-domain.com'),
- [dns.Record_NAPTR(100, 10, "u", "sip+E2U",
- "!^.*$!sip:[email protected]!",
+ [dns.Record_NAPTR(100, 10, b"u", b"sip+E2U",
+ b"!^.*$!sip:[email protected]!",
ttl=19283784)])
@@ -510,7 +525,7 @@
def test_empty(self):
resolvConf = self.mktemp()
- fObj = file(resolvConf, 'w')
+ fObj = open(resolvConf, 'w')
fObj.close()
r = client.Resolver(resolv=resolvConf)
self.assertEqual(r.dynServers, [('127.0.0.1', 53)])
@@ -533,7 +548,7 @@
nothing to do with the zone example.com.
"""
testDomain = test_domain_com
- testDomainName = 'nonexistent.prefix-' + testDomain.soa[0]
+ testDomainName = b'nonexistent.prefix-' + testDomain.soa[0]
f = self.failureResultOf(testDomain.lookupAddress(testDomainName))
self.assertIsInstance(f.value, DomainError)
@@ -593,7 +608,7 @@
def test_referral(self):
"""
When an I{NS} record is found for a child zone, it is included in the
- authority section of the response. It is marked as non-authoritative if
+ authority section of the response. It is marked as non-authoritative if
the authority is not also authoritative for the child zone (RFC 2181,
section 6.1).
"""
@@ -667,7 +682,8 @@
@param computed: A L{list} of L{RRHeader} instances giving the records
computed by the scenario under test.
- @raise self.failureException: If the two collections of records disagree.
+ @raise self.failureException: If the two collections of records
+ disagree.
"""
# RRHeader instances aren't inherently ordered. Impose an ordering
# that's good enough for the purposes of these tests - in which we
@@ -969,7 +985,7 @@
msg = Message()
# DNSProtocol.writeMessage length encodes the message by prepending a
# 2 byte message length to the buffered value.
- msg.decode(StringIO(transport.value()[2:]))
+ msg.decode(BytesIO(transport.value()[2:]))
self.assertEqual(
[dns.Query('example.com', dns.AXFR, dns.IN)], msg.queries)
@@ -981,7 +997,7 @@
with the I{A} records the authority has cached from the primary.
"""
secondary = SecondaryAuthority.fromServerAddressAndDomain(
- (b'192.168.1.2', 1234), b'example.com')
+ ('192.168.1.2', 1234), b'example.com')
secondary._reactor = reactor = MemoryReactorClock()
secondary.transfer()
@@ -993,7 +1009,7 @@
proto.makeConnection(transport)
query = Message(answer=1, auth=1)
- query.decode(StringIO(transport.value()[2:]))
+ query.decode(BytesIO(transport.value()[2:]))
# Generate a response with some data we can check.
soa = Record_SOA(
Modified: trunk/twisted/python/dist3.py
==============================================================================
--- trunk/twisted/python/dist3.py (original)
+++ trunk/twisted/python/dist3.py Thu Apr 14 04:52:07 2016
@@ -124,6 +124,8 @@
"twisted.logger.test.__init__",
"twisted.names.__init__",
"twisted.names._rfc1982",
+ "twisted.names.authority",
+ "twisted.names.secondary",
"twisted.names.cache",
"twisted.names.client",
"twisted.names.common",
@@ -331,6 +333,8 @@
"twisted.names.test.test_rfc1982",
"twisted.names.test.test_server",
"twisted.names.test.test_util",
+ "twisted.names.test.test_names",
+ "twisted.names.test.test_examples",
"twisted.persisted.test.test_styles",
"twisted.positioning.test.test_base",
"twisted.positioning.test.test_nmea",