[flake8]
-ignore =
- # Prefer emacs indentation of continued lines
- E126,
- E127,
- E129,
- # Whitespace round parameter '=' can be excessive
- E252,
- # Multiple # in a comment is OK
- E266,
- # Not excited by the "two blank lines" rule
- E302,
- E305,
- # or the one blank line rule
- E306,
- # Ambigious variables are ok.
- E741,
- # Lines ending with binary operators are OK
- W504,
-
-max-line-length = 120
+extend-ignore = W503, E203, E266, E741, F401
+max-line-length = 88
[](https://opensource.org/licenses/ISC)
[](https://codecov.io/github/rthalley/dnspython)
[](https://lgtm.com/projects/g/rthalley/dnspython/)
+[](https://github.com/psf/black)
## INTRODUCTION
"""dnspython DNS toolkit"""
__all__ = [
- 'asyncbackend',
- 'asyncquery',
- 'asyncresolver',
- 'dnssec',
- 'dnssectypes',
- 'e164',
- 'edns',
- 'entropy',
- 'exception',
- 'flags',
- 'immutable',
- 'inet',
- 'ipv4',
- 'ipv6',
- 'message',
- 'name',
- 'namedict',
- 'node',
- 'opcode',
- 'query',
- 'rcode',
- 'rdata',
- 'rdataclass',
- 'rdataset',
- 'rdatatype',
- 'renderer',
- 'resolver',
- 'reversename',
- 'rrset',
- 'serial',
- 'set',
- 'tokenizer',
- 'transaction',
- 'tsig',
- 'tsigkeyring',
- 'ttl',
- 'rdtypes',
- 'update',
- 'version',
- 'versioned',
- 'wire',
- 'xfr',
- 'zone',
- 'zonetypes',
- 'zonefile',
+ "asyncbackend",
+ "asyncquery",
+ "asyncresolver",
+ "dnssec",
+ "dnssectypes",
+ "e164",
+ "edns",
+ "entropy",
+ "exception",
+ "flags",
+ "immutable",
+ "inet",
+ "ipv4",
+ "ipv6",
+ "message",
+ "name",
+ "namedict",
+ "node",
+ "opcode",
+ "query",
+ "rcode",
+ "rdata",
+ "rdataclass",
+ "rdataset",
+ "rdatatype",
+ "renderer",
+ "resolver",
+ "reversename",
+ "rrset",
+ "serial",
+ "set",
+ "tokenizer",
+ "transaction",
+ "tsig",
+ "tsigkeyring",
+ "ttl",
+ "rdtypes",
+ "update",
+ "version",
+ "versioned",
+ "wire",
+ "xfr",
+ "zone",
+ "zonetypes",
+ "zonefile",
]
from dns.version import version as __version__ # noqa
# This is a nullcontext for both sync and async. 3.7 has a nullcontext,
# but it is only for sync use.
+
class NullContext:
def __init__(self, enter_result=None):
self.enter_result = enter_result
# These are declared here so backends can import them without creating
# circular dependencies with dns.asyncbackend.
+
class Socket: # pragma: no cover
async def close(self):
pass
raise NotImplementedError
-class Backend: # pragma: no cover
+class Backend: # pragma: no cover
def name(self):
- return 'unknown'
-
- async def make_socket(self, af, socktype, proto=0,
- source=None, destination=None, timeout=None,
- ssl_context=None, server_hostname=None):
+ return "unknown"
+
+ async def make_socket(
+ self,
+ af,
+ socktype,
+ proto=0,
+ source=None,
+ destination=None,
+ timeout=None,
+ ssl_context=None,
+ server_hostname=None,
+ ):
raise NotImplementedError
def datagram_connection_required(self):
import dns.exception
-_is_win32 = sys.platform == 'win32'
+_is_win32 = sys.platform == "win32"
+
def _get_running_loop():
try:
self.protocol.close()
async def getpeername(self):
- return self.transport.get_extra_info('peername')
+ return self.transport.get_extra_info("peername")
async def getsockname(self):
- return self.transport.get_extra_info('sockname')
+ return self.transport.get_extra_info("sockname")
class StreamSocket(dns._asyncbackend.StreamSocket):
return await _maybe_wait_for(self.writer.drain(), timeout)
async def recv(self, size, timeout):
- return await _maybe_wait_for(self.reader.read(size),
- timeout)
+ return await _maybe_wait_for(self.reader.read(size), timeout)
async def close(self):
self.writer.close()
pass
async def getpeername(self):
- return self.writer.get_extra_info('peername')
+ return self.writer.get_extra_info("peername")
async def getsockname(self):
- return self.writer.get_extra_info('sockname')
+ return self.writer.get_extra_info("sockname")
class Backend(dns._asyncbackend.Backend):
def name(self):
- return 'asyncio'
-
- async def make_socket(self, af, socktype, proto=0,
- source=None, destination=None, timeout=None,
- ssl_context=None, server_hostname=None):
- if destination is None and socktype == socket.SOCK_DGRAM and \
- _is_win32:
- raise NotImplementedError('destinationless datagram sockets '
- 'are not supported by asyncio '
- 'on Windows')
+ return "asyncio"
+
+ async def make_socket(
+ self,
+ af,
+ socktype,
+ proto=0,
+ source=None,
+ destination=None,
+ timeout=None,
+ ssl_context=None,
+ server_hostname=None,
+ ):
+ if destination is None and socktype == socket.SOCK_DGRAM and _is_win32:
+ raise NotImplementedError(
+ "destinationless datagram sockets "
+ "are not supported by asyncio "
+ "on Windows"
+ )
loop = _get_running_loop()
if socktype == socket.SOCK_DGRAM:
transport, protocol = await loop.create_datagram_endpoint(
- _DatagramProtocol, source, family=af,
- proto=proto, remote_addr=destination)
+ _DatagramProtocol,
+ source,
+ family=af,
+ proto=proto,
+ remote_addr=destination,
+ )
return DatagramSocket(af, transport, protocol)
elif socktype == socket.SOCK_STREAM:
(r, w) = await _maybe_wait_for(
- asyncio.open_connection(destination[0],
- destination[1],
- ssl=ssl_context,
- family=af,
- proto=proto,
- local_addr=source,
- server_hostname=server_hostname),
- timeout)
+ asyncio.open_connection(
+ destination[0],
+ destination[1],
+ ssl=ssl_context,
+ family=af,
+ proto=proto,
+ local_addr=source,
+ server_hostname=server_hostname,
+ ),
+ timeout,
+ )
return StreamSocket(af, r, w)
- raise NotImplementedError('unsupported socket ' +
- f'type {socktype}') # pragma: no cover
+ raise NotImplementedError(
+ "unsupported socket " + f"type {socktype}"
+ ) # pragma: no cover
async def sleep(self, interval):
await asyncio.sleep(interval)
async def sendto(self, what, destination, timeout):
async with _maybe_timeout(timeout):
return await self.socket.sendto(what, destination)
- raise dns.exception.Timeout(timeout=timeout) # pragma: no cover lgtm[py/unreachable-statement]
+ raise dns.exception.Timeout(
+ timeout=timeout
+ ) # pragma: no cover lgtm[py/unreachable-statement]
async def recvfrom(self, size, timeout):
async with _maybe_timeout(timeout):
class Backend(dns._asyncbackend.Backend):
def name(self):
- return 'curio'
-
- async def make_socket(self, af, socktype, proto=0,
- source=None, destination=None, timeout=None,
- ssl_context=None, server_hostname=None):
+ return "curio"
+
+ async def make_socket(
+ self,
+ af,
+ socktype,
+ proto=0,
+ source=None,
+ destination=None,
+ timeout=None,
+ ssl_context=None,
+ server_hostname=None,
+ ):
if socktype == socket.SOCK_DGRAM:
s = curio.socket.socket(af, socktype, proto)
try:
else:
source_addr = None
async with _maybe_timeout(timeout):
- s = await curio.open_connection(destination[0], destination[1],
- ssl=ssl_context,
- source_addr=source_addr,
- server_hostname=server_hostname)
+ s = await curio.open_connection(
+ destination[0],
+ destination[1],
+ ssl=ssl_context,
+ source_addr=source_addr,
+ server_hostname=server_hostname,
+ )
return StreamSocket(s)
- raise NotImplementedError('unsupported socket ' +
- f'type {socktype}') # pragma: no cover
+ raise NotImplementedError(
+ "unsupported socket " + f"type {socktype}"
+ ) # pragma: no cover
async def sleep(self, interval):
await curio.sleep(interval)
import inspect
-_in__init__ = contextvars.ContextVar('_immutable_in__init__', default=False)
+_in__init__ = contextvars.ContextVar("_immutable_in__init__", default=False)
class _Immutable:
f(*args, **kwargs)
finally:
_in__init__.reset(previous)
+
nf.__signature__ = inspect.signature(f)
return nf
# Some ancestor already has the mixin, so just make sure we keep
# following the __init__ protocol.
cls.__init__ = _immutable_init(cls.__init__)
- if hasattr(cls, '__setstate__'):
+ if hasattr(cls, "__setstate__"):
cls.__setstate__ = _immutable_init(cls.__setstate__)
ncls = cls
else:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- if hasattr(cls, '__setstate__'):
+ if hasattr(cls, "__setstate__"):
+
@_immutable_init
def __setstate__(self, *args, **kwargs):
super().__setstate__(*args, **kwargs)
async def sendto(self, what, destination, timeout):
with _maybe_timeout(timeout):
return await self.socket.sendto(what, destination)
- raise dns.exception.Timeout(timeout=timeout) # pragma: no cover lgtm[py/unreachable-statement]
+ raise dns.exception.Timeout(
+ timeout=timeout
+ ) # pragma: no cover lgtm[py/unreachable-statement]
async def recvfrom(self, size, timeout):
with _maybe_timeout(timeout):
class Backend(dns._asyncbackend.Backend):
def name(self):
- return 'trio'
-
- async def make_socket(self, af, socktype, proto=0, source=None,
- destination=None, timeout=None,
- ssl_context=None, server_hostname=None):
+ return "trio"
+
+ async def make_socket(
+ self,
+ af,
+ socktype,
+ proto=0,
+ source=None,
+ destination=None,
+ timeout=None,
+ ssl_context=None,
+ server_hostname=None,
+ ):
s = trio.socket.socket(af, socktype, proto)
stream = None
try:
if ssl_context:
tls = True
try:
- stream = trio.SSLStream(stream, ssl_context,
- server_hostname=server_hostname)
+ stream = trio.SSLStream(
+ stream, ssl_context, server_hostname=server_hostname
+ )
except Exception: # pragma: no cover
await stream.aclose()
raise
return StreamSocket(af, stream, tls)
- raise NotImplementedError('unsupported socket ' +
- f'type {socktype}') # pragma: no cover
+ raise NotImplementedError(
+ "unsupported socket " + f"type {socktype}"
+ ) # pragma: no cover
async def sleep(self, interval):
await trio.sleep(interval)
# pylint: disable=unused-import
-from dns._asyncbackend import Socket, DatagramSocket, StreamSocket, Backend # noqa: F401 lgtm[py/unused-import]
+from dns._asyncbackend import (
+ Socket,
+ DatagramSocket,
+ StreamSocket,
+ Backend,
+) # noqa: F401 lgtm[py/unused-import]
# pylint: enable=unused-import
# Allow sniffio import to be disabled for testing purposes
_no_sniffio = False
+
class AsyncLibraryNotFoundError(dns.exception.DNSException):
pass
backend = _backends.get(name)
if backend:
return backend
- if name == 'trio':
+ if name == "trio":
import dns._trio_backend
+
backend = dns._trio_backend.Backend()
- elif name == 'curio':
+ elif name == "curio":
import dns._curio_backend
+
backend = dns._curio_backend.Backend()
- elif name == 'asyncio':
+ elif name == "asyncio":
import dns._asyncio_backend
+
backend = dns._asyncio_backend.Backend()
else:
- raise NotImplementedError(f'unimplemented async backend {name}')
+ raise NotImplementedError(f"unimplemented async backend {name}")
_backends[name] = backend
return backend
if _no_sniffio:
raise ImportError
import sniffio
+
try:
return sniffio.current_async_library()
except sniffio.AsyncLibraryNotFoundError:
- raise AsyncLibraryNotFoundError('sniffio cannot determine ' +
- 'async library')
+ raise AsyncLibraryNotFoundError(
+ "sniffio cannot determine " + "async library"
+ )
except ImportError:
import asyncio
+
try:
asyncio.get_running_loop()
- return 'asyncio'
+ return "asyncio"
except RuntimeError:
- raise AsyncLibraryNotFoundError('no async library detected')
+ raise AsyncLibraryNotFoundError("no async library detected")
def get_default_backend() -> Backend:
- """Get the default backend, initializing it if necessary.
- """
+ """Get the default backend, initializing it if necessary."""
if _default_backend:
return _default_backend
import dns.rdatatype
import dns.transaction
-from dns.query import _compute_times, _matches_destination, BadResponse, ssl, \
- UDPMode, _have_httpx, _have_http2, NoDOH
+from dns.query import (
+ _compute_times,
+ _matches_destination,
+ BadResponse,
+ ssl,
+ UDPMode,
+ _have_httpx,
+ _have_http2,
+ NoDOH,
+)
if _have_httpx:
import httpx
if address or port:
if address is None:
if af == socket.AF_INET:
- address = '0.0.0.0'
+ address = "0.0.0.0"
elif af == socket.AF_INET6:
- address = '::'
+ address = "::"
else:
- raise NotImplementedError(f'unknown address family {af}')
+ raise NotImplementedError(f"unknown address family {af}")
return (address, port)
else:
return None
return None
-async def send_udp(sock: dns.asyncbackend.DatagramSocket,
- what: Union[dns.message.Message, bytes], destination: Any,
- expiration: Optional[float]=None) -> Tuple[int, float]:
+async def send_udp(
+ sock: dns.asyncbackend.DatagramSocket,
+ what: Union[dns.message.Message, bytes],
+ destination: Any,
+ expiration: Optional[float] = None,
+) -> Tuple[int, float]:
"""Send a DNS message to the specified UDP socket.
*sock*, a ``dns.asyncbackend.DatagramSocket``.
return (n, sent_time)
-async def receive_udp(sock: dns.asyncbackend.DatagramSocket,
- destination: Optional[Any]=None, expiration: Optional[float]=None,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False,
- keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]]=None, request_mac: Optional[bytes]=b'',
- ignore_trailing: bool=False, raise_on_truncation: bool=False) -> Any:
+async def receive_udp(
+ sock: dns.asyncbackend.DatagramSocket,
+ destination: Optional[Any] = None,
+ expiration: Optional[float] = None,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None,
+ request_mac: Optional[bytes] = b"",
+ ignore_trailing: bool = False,
+ raise_on_truncation: bool = False,
+) -> Any:
"""Read a DNS message from a UDP socket.
*sock*, a ``dns.asyncbackend.DatagramSocket``.
parameters, exceptions, and return type of this method.
"""
- wire = b''
+ wire = b""
while 1:
(wire, from_address) = await sock.recvfrom(65535, _timeout(expiration))
- if _matches_destination(sock.family, from_address, destination,
- ignore_unexpected):
+ if _matches_destination(
+ sock.family, from_address, destination, ignore_unexpected
+ ):
break
received_time = time.time()
- r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing,
- raise_on_truncation=raise_on_truncation)
+ r = dns.message.from_wire(
+ wire,
+ keyring=keyring,
+ request_mac=request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ raise_on_truncation=raise_on_truncation,
+ )
return (r, received_time, from_address)
-async def udp(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- raise_on_truncation: bool=False, sock: Optional[dns.asyncbackend.DatagramSocket]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> dns.message.Message:
+
+async def udp(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ raise_on_truncation: bool = False,
+ sock: Optional[dns.asyncbackend.DatagramSocket] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via UDP.
*sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``,
dtuple = (where, port)
else:
dtuple = None
- s = await backend.make_socket(af, socket.SOCK_DGRAM, 0, stuple,
- dtuple)
+ s = await backend.make_socket(af, socket.SOCK_DGRAM, 0, stuple, dtuple)
assert s is not None
await send_udp(s, wire, destination, expiration)
- (r, received_time, _) = await receive_udp(s, destination, expiration,
- ignore_unexpected,
- one_rr_per_rrset,
- q.keyring, q.mac,
- ignore_trailing,
- raise_on_truncation)
+ (r, received_time, _) = await receive_udp(
+ s,
+ destination,
+ expiration,
+ ignore_unexpected,
+ one_rr_per_rrset,
+ q.keyring,
+ q.mac,
+ ignore_trailing,
+ raise_on_truncation,
+ )
r.time = received_time - begin_time
if not q.is_response(r):
raise BadResponse
if not sock and s:
await s.close()
-async def udp_with_fallback(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- udp_sock: Optional[dns.asyncbackend.DatagramSocket]=None,
- tcp_sock: Optional[dns.asyncbackend.StreamSocket]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> Tuple[dns.message.Message, bool]:
+
+async def udp_with_fallback(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ udp_sock: Optional[dns.asyncbackend.DatagramSocket] = None,
+ tcp_sock: Optional[dns.asyncbackend.StreamSocket] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> Tuple[dns.message.Message, bool]:
"""Return the response to the query, trying UDP first and falling back
to TCP if UDP results in a truncated response.
method.
"""
try:
- response = await udp(q, where, timeout, port, source, source_port,
- ignore_unexpected, one_rr_per_rrset,
- ignore_trailing, True, udp_sock, backend)
+ response = await udp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ ignore_unexpected,
+ one_rr_per_rrset,
+ ignore_trailing,
+ True,
+ udp_sock,
+ backend,
+ )
return (response, False)
except dns.message.Truncated:
- response = await tcp(q, where, timeout, port, source, source_port,
- one_rr_per_rrset, ignore_trailing, tcp_sock,
- backend)
+ response = await tcp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ tcp_sock,
+ backend,
+ )
return (response, True)
-async def send_tcp(sock: dns.asyncbackend.StreamSocket,
- what: Union[dns.message.Message, bytes],
- expiration: Optional[float]=None) -> Tuple[int, float]:
+async def send_tcp(
+ sock: dns.asyncbackend.StreamSocket,
+ what: Union[dns.message.Message, bytes],
+ expiration: Optional[float] = None,
+) -> Tuple[int, float]:
"""Send a DNS message to the specified TCP socket.
*sock*, a ``dns.asyncbackend.StreamSocket``.
"""Read the specified number of bytes from stream. Keep trying until we
either get the desired amount, or we hit EOF.
"""
- s = b''
+ s = b""
while count > 0:
n = await sock.recv(count, _timeout(expiration))
- if n == b'':
+ if n == b"":
raise EOFError
count = count - len(n)
s = s + n
return s
-async def receive_tcp(sock: dns.asyncbackend.StreamSocket,
- expiration: Optional[float]=None, one_rr_per_rrset: bool=False,
- keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]]=None,
- request_mac: Optional[bytes]=b'',
- ignore_trailing: bool=False) -> Tuple[dns.message.Message, float]:
+async def receive_tcp(
+ sock: dns.asyncbackend.StreamSocket,
+ expiration: Optional[float] = None,
+ one_rr_per_rrset: bool = False,
+ keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None,
+ request_mac: Optional[bytes] = b"",
+ ignore_trailing: bool = False,
+) -> Tuple[dns.message.Message, float]:
"""Read a DNS message from a TCP socket.
*sock*, a ``dns.asyncbackend.StreamSocket``.
(l,) = struct.unpack("!H", ldata)
wire = await _read_exactly(sock, l, expiration)
received_time = time.time()
- r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing)
+ r = dns.message.from_wire(
+ wire,
+ keyring=keyring,
+ request_mac=request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
return (r, received_time)
-async def tcp(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- sock: Optional[dns.asyncbackend.StreamSocket]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> dns.message.Message:
+async def tcp(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ sock: Optional[dns.asyncbackend.StreamSocket] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via TCP.
*sock*, a ``dns.asyncbacket.StreamSocket``, or ``None``, the
dtuple = (where, port)
if not backend:
backend = dns.asyncbackend.get_default_backend()
- s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple,
- dtuple, timeout)
+ s = await backend.make_socket(
+ af, socket.SOCK_STREAM, 0, stuple, dtuple, timeout
+ )
assert s is not None
await send_tcp(s, wire, expiration)
- (r, received_time) = await receive_tcp(s, expiration, one_rr_per_rrset,
- q.keyring, q.mac,
- ignore_trailing)
+ (r, received_time) = await receive_tcp(
+ s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing
+ )
r.time = received_time - begin_time
if not q.is_response(r):
raise BadResponse
if not sock and s:
await s.close()
-async def tls(q: dns.message.Message, where: str, timeout: Optional[float]=None,
- port: int=853, source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- sock: Optional[dns.asyncbackend.StreamSocket]=None,
- backend: Optional[dns.asyncbackend.Backend]=None,
- ssl_context: Optional[ssl.SSLContext]=None,
- server_hostname: Optional[str]=None) -> dns.message.Message:
+
+async def tls(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 853,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ sock: Optional[dns.asyncbackend.StreamSocket] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+ ssl_context: Optional[ssl.SSLContext] = None,
+ server_hostname: Optional[str] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via TLS.
*sock*, an ``asyncbackend.StreamSocket``, or ``None``, the socket
dtuple = (where, port)
if not backend:
backend = dns.asyncbackend.get_default_backend()
- s = await backend.make_socket(af, socket.SOCK_STREAM, 0, stuple,
- dtuple, timeout, ssl_context,
- server_hostname)
+ s = await backend.make_socket(
+ af,
+ socket.SOCK_STREAM,
+ 0,
+ stuple,
+ dtuple,
+ timeout,
+ ssl_context,
+ server_hostname,
+ )
else:
s = sock
try:
timeout = _timeout(expiration)
- response = await tcp(q, where, timeout, port, source, source_port,
- one_rr_per_rrset, ignore_trailing, s, backend)
+ response = await tcp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ s,
+ backend,
+ )
end_time = time.time()
response.time = end_time - begin_time
return response
if not sock and s:
await s.close()
-async def https(q: dns.message.Message, where: str, timeout: Optional[float]=None,
- port: int=443, source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- client: Optional[httpx.AsyncClient]=None,
- path: str='/dns-query', post: bool=True, verify: bool=True) -> dns.message.Message:
+
+async def https(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 443,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ client: Optional[httpx.AsyncClient] = None,
+ path: str = "/dns-query",
+ post: bool = True,
+ verify: bool = True,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via DNS-over-HTTPS.
*client*, a ``httpx.AsyncClient``. If provided, the client to use for
"""
if not _have_httpx:
- raise NoDOH('httpx is not available.') # pragma: no cover
+ raise NoDOH("httpx is not available.") # pragma: no cover
wire = q.to_wire()
try:
except ValueError:
af = None
transport = None
- headers = {
- "accept": "application/dns-message"
- }
+ headers = {"accept": "application/dns-message"}
if af is not None:
if af == socket.AF_INET:
- url = 'https://{}:{}{}'.format(where, port, path)
+ url = "https://{}:{}{}".format(where, port, path)
elif af == socket.AF_INET6:
- url = 'https://[{}]:{}{}'.format(where, port, path)
+ url = "https://[{}]:{}{}".format(where, port, path)
else:
url = where
if source is not None:
client_to_close = None
try:
if not client:
- client = httpx.AsyncClient(http1=True, http2=_have_http2,
- verify=verify, transport=transport)
+ client = httpx.AsyncClient(
+ http1=True, http2=_have_http2, verify=verify, transport=transport
+ )
client_to_close = client
# see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
# GET and POST examples
if post:
- headers.update({
- "content-type": "application/dns-message",
- "content-length": str(len(wire))
- })
- response = await client.post(url, headers=headers, content=wire,
- timeout=timeout)
+ headers.update(
+ {
+ "content-type": "application/dns-message",
+ "content-length": str(len(wire)),
+ }
+ )
+ response = await client.post(
+ url, headers=headers, content=wire, timeout=timeout
+ )
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
twire = wire.decode() # httpx does a repr() if we give it bytes
- response = await client.get(url, headers=headers, timeout=timeout,
- params={"dns": twire})
+ response = await client.get(
+ url, headers=headers, timeout=timeout, params={"dns": twire}
+ )
finally:
if client_to_close:
await client_to_close.aclose()
# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
# status codes
if response.status_code < 200 or response.status_code > 299:
- raise ValueError('{} responded with status code {}'
- '\nResponse body: {!r}'.format(where,
- response.status_code,
- response.content))
- r = dns.message.from_wire(response.content,
- keyring=q.keyring,
- request_mac=q.request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing)
+ raise ValueError(
+ "{} responded with status code {}"
+ "\nResponse body: {!r}".format(
+ where, response.status_code, response.content
+ )
+ )
+ r = dns.message.from_wire(
+ response.content,
+ keyring=q.keyring,
+ request_mac=q.request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
r.time = response.elapsed.total_seconds()
if not q.is_response(r):
raise BadResponse
return r
-async def inbound_xfr(where: str, txn_manager: dns.transaction.TransactionManager,
- query: Optional[dns.message.Message]=None,
- port: int=53, timeout: Optional[float]=None, lifetime: Optional[float]=None,
- source: Optional[str]=None, source_port: int=0, udp_mode: UDPMode=UDPMode.NEVER,
- backend: Optional[dns.asyncbackend.Backend]=None) -> None:
+
+async def inbound_xfr(
+ where: str,
+ txn_manager: dns.transaction.TransactionManager,
+ query: Optional[dns.message.Message] = None,
+ port: int = 53,
+ timeout: Optional[float] = None,
+ lifetime: Optional[float] = None,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ udp_mode: UDPMode = UDPMode.NEVER,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> None:
"""Conduct an inbound transfer and apply it via a transaction from the
txn_manager.
is_udp = False
if not backend:
backend = dns.asyncbackend.get_default_backend()
- s = await backend.make_socket(af, sock_type, 0, stuple, dtuple,
- _timeout(expiration))
+ s = await backend.make_socket(
+ af, sock_type, 0, stuple, dtuple, _timeout(expiration)
+ )
async with s:
if is_udp:
await s.sendto(wire, dtuple, _timeout(expiration))
else:
tcpmsg = struct.pack("!H", len(wire)) + wire
await s.sendall(tcpmsg, expiration)
- with dns.xfr.Inbound(txn_manager, rdtype, serial,
- is_udp) as inbound:
+ with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
done = False
tsig_ctx = None
while not done:
(_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or \
- (expiration is not None and mexpiration > expiration):
+ if mexpiration is None or (
+ expiration is not None and mexpiration > expiration
+ ):
mexpiration = expiration
if is_udp:
destination = _lltuple((where, port), af)
while True:
timeout = _timeout(mexpiration)
- (rwire, from_address) = await s.recvfrom(65535,
- timeout)
- if _matches_destination(af, from_address,
- destination, True):
+ (rwire, from_address) = await s.recvfrom(65535, timeout)
+ if _matches_destination(
+ af, from_address, destination, True
+ ):
break
else:
ldata = await _read_exactly(s, 2, mexpiration)
(l,) = struct.unpack("!H", ldata)
rwire = await _read_exactly(s, l, mexpiration)
- is_ixfr = (rdtype == dns.rdatatype.IXFR)
- r = dns.message.from_wire(rwire, keyring=query.keyring,
- request_mac=query.mac, xfr=True,
- origin=origin, tsig_ctx=tsig_ctx,
- multi=(not is_udp),
- one_rr_per_rrset=is_ixfr)
+ is_ixfr = rdtype == dns.rdatatype.IXFR
+ r = dns.message.from_wire(
+ rwire,
+ keyring=query.keyring,
+ request_mac=query.mac,
+ xfr=True,
+ origin=origin,
+ tsig_ctx=tsig_ctx,
+ multi=(not is_udp),
+ one_rr_per_rrset=is_ixfr,
+ )
try:
done = inbound.process_message(r)
except dns.xfr.UseTCP:
class Resolver(dns.resolver.BaseResolver):
"""Asynchronous DNS stub resolver."""
- async def resolve(self, qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- tcp: bool=False, source: Optional[str]=None,
- raise_on_no_answer: bool=True, source_port: int=0,
- lifetime: Optional[float]=None, search: Optional[bool]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> dns.resolver.Answer:
+ async def resolve(
+ self,
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+ search: Optional[bool] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+ ) -> dns.resolver.Answer:
"""Query nameservers asynchronously to find the answer to the question.
*backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``,
type of this method.
"""
- resolution = dns.resolver._Resolution(self, qname, rdtype, rdclass, tcp,
- raise_on_no_answer, search)
+ resolution = dns.resolver._Resolution(
+ self, qname, rdtype, rdclass, tcp, raise_on_no_answer, search
+ )
if not backend:
backend = dns.asyncbackend.get_default_backend()
start = time.time()
(nameserver, port, tcp, backoff) = resolution.next_nameserver()
if backoff:
await backend.sleep(backoff)
- timeout = self._compute_timeout(start, lifetime,
- resolution.errors)
+ timeout = self._compute_timeout(start, lifetime, resolution.errors)
try:
if dns.inet.is_address(nameserver):
if tcp:
- response = await _tcp(request, nameserver,
- timeout, port,
- source, source_port,
- backend=backend)
+ response = await _tcp(
+ request,
+ nameserver,
+ timeout,
+ port,
+ source,
+ source_port,
+ backend=backend,
+ )
else:
- response = await _udp(request, nameserver,
- timeout, port,
- source, source_port,
- raise_on_truncation=True,
- backend=backend)
+ response = await _udp(
+ request,
+ nameserver,
+ timeout,
+ port,
+ source,
+ source_port,
+ raise_on_truncation=True,
+ backend=backend,
+ )
else:
- response = await dns.asyncquery.https(request,
- nameserver,
- timeout=timeout)
+ response = await dns.asyncquery.https(
+ request, nameserver, timeout=timeout
+ )
except Exception as ex:
(_, done) = resolution.query_result(None, ex)
continue
if answer is not None:
return answer
- async def resolve_address(self, ipaddr: str, *args: Any, **kwargs: Dict[str, Any]) -> dns.resolver.Answer:
+ async def resolve_address(
+ self, ipaddr: str, *args: Any, **kwargs: Dict[str, Any]
+ ) -> dns.resolver.Answer:
"""Use an asynchronous resolver to run a reverse query for PTR
records.
# in the kwargs more than once.
modified_kwargs: Dict[str, Any] = {}
modified_kwargs.update(kwargs)
- modified_kwargs['rdtype'] = dns.rdatatype.PTR
- modified_kwargs['rdclass'] = dns.rdataclass.IN
- return await self.resolve(dns.reversename.from_address(ipaddr),
- *args, **modified_kwargs)
+ modified_kwargs["rdtype"] = dns.rdatatype.PTR
+ modified_kwargs["rdclass"] = dns.rdataclass.IN
+ return await self.resolve(
+ dns.reversename.from_address(ipaddr), *args, **modified_kwargs
+ )
# pylint: disable=redefined-outer-name
default_resolver = Resolver()
-async def resolve(qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- tcp: bool=False, source: Optional[str]=None,
- raise_on_no_answer: bool=True, source_port: int=0,
- lifetime: Optional[float]=None, search: Optional[bool]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> dns.resolver.Answer:
+async def resolve(
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+ search: Optional[bool] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> dns.resolver.Answer:
"""Query nameservers asynchronously to find the answer to the question.
This is a convenience function that uses the default resolver
information on the parameters.
"""
- return await get_default_resolver().resolve(qname, rdtype, rdclass, tcp,
- source, raise_on_no_answer,
- source_port, lifetime, search,
- backend)
-
-
-async def resolve_address(ipaddr: str, *args: Any, **kwargs: Dict[str, Any]) -> dns.resolver.Answer:
+ return await get_default_resolver().resolve(
+ qname,
+ rdtype,
+ rdclass,
+ tcp,
+ source,
+ raise_on_no_answer,
+ source_port,
+ lifetime,
+ search,
+ backend,
+ )
+
+
+async def resolve_address(
+ ipaddr: str, *args: Any, **kwargs: Dict[str, Any]
+) -> dns.resolver.Answer:
"""Use a resolver to run a reverse query for PTR records.
See :py:func:`dns.asyncresolver.Resolver.resolve_address` for more
return await get_default_resolver().resolve_address(ipaddr, *args, **kwargs)
+
async def canonical_name(name: Union[dns.name.Name, str]) -> dns.name.Name:
"""Determine the canonical name of *name*.
return await get_default_resolver().canonical_name(name)
-async def zone_for_name(name: Union[dns.name.Name, str],
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN,
- tcp: bool=False, resolver: Optional[Resolver]=None,
- backend: Optional[dns.asyncbackend.Backend]=None) -> dns.name.Name:
+
+async def zone_for_name(
+ name: Union[dns.name.Name, str],
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ tcp: bool = False,
+ resolver: Optional[Resolver] = None,
+ backend: Optional[dns.asyncbackend.Backend] = None,
+) -> dns.name.Name:
"""Find the name of the zone which contains the specified name.
See :py:func:`dns.resolver.Resolver.zone_for_name` for more
raise NotAbsolute(name)
while True:
try:
- answer = await resolver.resolve(name, dns.rdatatype.SOA, rdclass,
- tcp, backend=backend)
+ answer = await resolver.resolve(
+ name, dns.rdatatype.SOA, rdclass, tcp, backend=backend
+ )
assert answer.rrset is not None
if answer.rrset.name == name:
return name
else:
total = 0
for i in range(len(rdata) // 2):
- total += (rdata[2 * i] << 8) + \
- rdata[2 * i + 1]
+ total += (rdata[2 * i] << 8) + rdata[2 * i + 1]
if len(rdata) % 2 != 0:
total += rdata[len(rdata) - 1] << 8
- total += ((total >> 16) & 0xffff)
- return total & 0xffff
+ total += (total >> 16) & 0xFFFF
+ return total & 0xFFFF
-def make_ds(name: Union[dns.name.Name, str], key: dns.rdata.Rdata,
- algorithm: Union[DSDigest, str],
- origin: Optional[dns.name.Name]=None) -> DS:
+def make_ds(
+ name: Union[dns.name.Name, str],
+ key: dns.rdata.Rdata,
+ algorithm: Union[DSDigest, str],
+ origin: Optional[dns.name.Name] = None,
+) -> DS:
"""Create a DS record for a DNSSEC key.
*name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record.
except Exception:
raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
if not isinstance(key, DNSKEY):
- raise ValueError('key is not a DNSKEY')
+ raise ValueError("key is not a DNSKEY")
if algorithm == DSDigest.SHA1:
dshash = hashlib.sha1()
elif algorithm == DSDigest.SHA256:
dshash.update(key.to_wire(origin=origin))
digest = dshash.digest()
- dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + \
- digest
- ds = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0,
- len(dsrdata))
+ dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + digest
+ ds = dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, len(dsrdata)
+ )
return cast(DS, ds)
-def _find_candidate_keys(keys: Dict[dns.name.Name, Union[dns.rdataset.Rdataset, dns.node.Node]],
- rrsig: RRSIG) -> Optional[List[DNSKEY]]:
+def _find_candidate_keys(
+ keys: Dict[dns.name.Name, Union[dns.rdataset.Rdataset, dns.node.Node]], rrsig: RRSIG
+) -> Optional[List[DNSKEY]]:
value = keys.get(rrsig.signer)
if isinstance(value, dns.node.Node):
rdataset = value.get_rdataset(dns.rdataclass.IN, dns.rdatatype.DNSKEY)
rdataset = value
if rdataset is None:
return None
- return [cast(DNSKEY, rd) for rd in rdataset if
- rd.algorithm == rrsig.algorithm and key_id(rd) == rrsig.key_tag]
+ return [
+ cast(DNSKEY, rd)
+ for rd in rdataset
+ if rd.algorithm == rrsig.algorithm and key_id(rd) == rrsig.key_tag
+ ]
def _is_rsa(algorithm: int) -> bool:
- return algorithm in (Algorithm.RSAMD5, Algorithm.RSASHA1,
- Algorithm.RSASHA1NSEC3SHA1, Algorithm.RSASHA256,
- Algorithm.RSASHA512)
+ return algorithm in (
+ Algorithm.RSAMD5,
+ Algorithm.RSASHA1,
+ Algorithm.RSASHA1NSEC3SHA1,
+ Algorithm.RSASHA256,
+ Algorithm.RSASHA512,
+ )
def _is_dsa(algorithm: int) -> bool:
def _is_sha1(algorithm: int) -> bool:
- return algorithm in (Algorithm.DSA, Algorithm.RSASHA1,
- Algorithm.DSANSEC3SHA1, Algorithm.RSASHA1NSEC3SHA1)
+ return algorithm in (
+ Algorithm.DSA,
+ Algorithm.RSASHA1,
+ Algorithm.DSANSEC3SHA1,
+ Algorithm.RSASHA1NSEC3SHA1,
+ )
def _is_sha256(algorithm: int) -> bool:
if algorithm == Algorithm.ED448:
return hashes.SHAKE256(114)
- raise ValidationFailure('unknown hash for algorithm %u' % algorithm)
+ raise ValidationFailure("unknown hash for algorithm %u" % algorithm)
def _bytes_to_long(b: bytes) -> int:
- return int.from_bytes(b, 'big')
+ return int.from_bytes(b, "big")
def _validate_signature(sig: bytes, data: bytes, key: DNSKEY, chosen_hash: Any) -> None:
keyptr: bytes
if _is_rsa(key.algorithm):
- # we ignore because mypy is confused and thinks key.key is a str for unknown reasons.
+ # we ignore because mypy is confused and thinks key.key is a str for unknown
+ # reasons.
keyptr = 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])
+ (bytes_,) = struct.unpack("!H", keyptr[0:2])
keyptr = keyptr[2:]
rsa_e = keyptr[0:bytes_]
rsa_n = keyptr[bytes_:]
try:
rsa_public_key = rsa.RSAPublicNumbers(
- _bytes_to_long(rsa_e),
- _bytes_to_long(rsa_n)).public_key(default_backend())
+ _bytes_to_long(rsa_e), _bytes_to_long(rsa_n)
+ ).public_key(default_backend())
except ValueError:
- raise ValidationFailure('invalid public key')
+ raise ValidationFailure("invalid public key")
rsa_public_key.verify(sig, data, padding.PKCS1v15(), chosen_hash)
elif _is_dsa(key.algorithm):
keyptr = key.key
- (t,) = struct.unpack('!B', keyptr[0:1])
+ (t,) = struct.unpack("!B", keyptr[0:1])
keyptr = keyptr[1:]
octets = 64 + t * 8
dsa_q = keyptr[0:20]
dsa_public_key = dsa.DSAPublicNumbers(
_bytes_to_long(dsa_y),
dsa.DSAParameterNumbers(
- _bytes_to_long(dsa_p),
- _bytes_to_long(dsa_q),
- _bytes_to_long(dsa_g))).public_key(default_backend())
+ _bytes_to_long(dsa_p), _bytes_to_long(dsa_q), _bytes_to_long(dsa_g)
+ ),
+ ).public_key(default_backend())
except ValueError:
- raise ValidationFailure('invalid public key')
+ raise ValidationFailure("invalid public key")
dsa_public_key.verify(sig, data, chosen_hash)
elif _is_ecdsa(key.algorithm):
keyptr = key.key
curve = ec.SECP384R1()
octets = 48
ecdsa_x = keyptr[0:octets]
- ecdsa_y = keyptr[octets:octets * 2]
+ ecdsa_y = keyptr[octets : octets * 2]
try:
ecdsa_public_key = ec.EllipticCurvePublicNumbers(
- curve=curve,
- x=_bytes_to_long(ecdsa_x),
- y=_bytes_to_long(ecdsa_y)).public_key(default_backend())
+ curve=curve, x=_bytes_to_long(ecdsa_x), y=_bytes_to_long(ecdsa_y)
+ ).public_key(default_backend())
except ValueError:
- raise ValidationFailure('invalid public key')
+ raise ValidationFailure("invalid public key")
ecdsa_public_key.verify(sig, data, ec.ECDSA(chosen_hash))
elif _is_eddsa(key.algorithm):
keyptr = key.key
try:
eddsa_public_key = loader.from_public_bytes(keyptr)
except ValueError:
- raise ValidationFailure('invalid public key')
+ raise ValidationFailure("invalid public key")
eddsa_public_key.verify(sig, data)
elif _is_gost(key.algorithm):
raise UnsupportedAlgorithm(
- 'algorithm "%s" not supported by dnspython' %
- algorithm_to_text(key.algorithm))
+ 'algorithm "%s" not supported by dnspython'
+ % algorithm_to_text(key.algorithm)
+ )
else:
- raise ValidationFailure('unknown algorithm %u' % key.algorithm)
+ raise ValidationFailure("unknown algorithm %u" % key.algorithm)
-def _validate_rrsig(rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
- rrsig: RRSIG,
- keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]],
- origin: Optional[dns.name.Name]=None, now: Optional[float]=None) -> None:
+def _validate_rrsig(
+ rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
+ rrsig: RRSIG,
+ keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]],
+ origin: Optional[dns.name.Name] = None,
+ now: Optional[float] = None,
+) -> None:
"""Validate an RRset against a single signature rdata, throwing an
exception if validation is not successful.
candidate_keys = _find_candidate_keys(keys, rrsig)
if candidate_keys is None:
- 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
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")
if _is_dsa(rrsig.algorithm):
sig_r = rrsig.signature[1:21]
sig_s = rrsig.signature[21:]
- sig = utils.encode_dss_signature(_bytes_to_long(sig_r),
- _bytes_to_long(sig_s))
+ sig = utils.encode_dss_signature(_bytes_to_long(sig_r), _bytes_to_long(sig_s))
elif _is_ecdsa(rrsig.algorithm):
if rrsig.algorithm == Algorithm.ECDSAP256SHA256:
octets = 32
octets = 48
sig_r = rrsig.signature[0:octets]
sig_s = rrsig.signature[octets:]
- sig = utils.encode_dss_signature(_bytes_to_long(sig_r),
- _bytes_to_long(sig_s))
+ sig = utils.encode_dss_signature(_bytes_to_long(sig_r), _bytes_to_long(sig_s))
else:
sig = rrsig.signature
- data = b''
+ data = b""
data += rrsig.to_wire(origin=origin)[:18]
data += rrsig.signer.to_digestable(origin)
# Derelativize the name before considering labels.
if not rrname.is_absolute():
if origin is None:
- raise ValidationFailure('relative RR name without an origin specified')
+ raise ValidationFailure("relative RR name without an origin specified")
rrname = rrname.derelativize(origin)
if len(rrname) - 1 < rrsig.labels:
- raise ValidationFailure('owner name longer than RRSIG labels')
+ raise ValidationFailure("owner name longer than RRSIG labels")
elif rrsig.labels < len(rrname) - 1:
suffix = rrname.split(rrsig.labels + 1)[1]
- rrname = dns.name.from_text('*', suffix)
+ rrname = dns.name.from_text("*", suffix)
rrnamebuf = rrname.to_digestable()
- rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass,
- rrsig.original_ttl)
+ rrfixed = struct.pack("!HHI", rdataset.rdtype, rdataset.rdclass, rrsig.original_ttl)
rdatas = [rdata.to_digestable(origin) for rdata in rdataset]
for rdata in sorted(rdatas):
data += rrnamebuf
data += rrfixed
- rrlen = struct.pack('!H', len(rdata))
+ rrlen = struct.pack("!H", len(rdata))
data += rrlen
data += rdata
# this happens on an individual validation failure
continue
# nothing verified -- raise failure:
- raise ValidationFailure('verify failure')
+ raise ValidationFailure("verify failure")
-def _validate(rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
- rrsigset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
- keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]],
- origin: Optional[dns.name.Name]=None, now: Optional[float]=None) -> None:
+def _validate(
+ rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
+ rrsigset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]],
+ keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]],
+ origin: Optional[dns.name.Name] = None,
+ now: Optional[float] = None,
+) -> None:
"""Validate an RRset against a signature RRset, throwing an exception
if none of the signatures validate.
for rrsig in rrsigrdataset:
if not isinstance(rrsig, RRSIG):
- raise ValidationFailure('expected an RRSIG')
+ raise ValidationFailure("expected an RRSIG")
try:
_validate_rrsig(rrset, rrsig, keys, origin, now)
return
raise ValidationFailure("no RRSIGs validated")
-def nsec3_hash(domain: Union[dns.name.Name, str], salt: Optional[Union[str, bytes]],
- iterations: int, algorithm: Union[int, str]) -> str:
+def nsec3_hash(
+ domain: Union[dns.name.Name, str],
+ salt: Optional[Union[str, bytes]],
+ iterations: int,
+ algorithm: Union[int, str],
+) -> str:
"""
Calculate the NSEC3 hash, according to
https://tools.ietf.org/html/rfc5155#section-5
raise ValueError("Wrong hash algorithm (only SHA1 is supported)")
if salt is None:
- salt_encoded = b''
+ salt_encoded = b""
elif isinstance(salt, str):
if len(salt) % 2 == 0:
salt_encoded = bytes.fromhex(salt)
def _need_pyca(*args, **kwargs):
- raise ImportError("DNSSEC validation requires " +
- "python cryptography") # pragma: no cover
+ raise ImportError(
+ "DNSSEC validation requires " + "python cryptography"
+ ) # pragma: no cover
try:
validate_rrsig = _need_pyca
_have_pyca = False
else:
- validate = _validate # type: ignore
- validate_rrsig = _validate_rrsig # type: ignore
+ validate = _validate # type: ignore
+ validate_rrsig = _validate_rrsig # type: ignore
_have_pyca = True
### BEGIN generated Algorithm constants
import dns.resolver
#: The public E.164 domain.
-public_enum_domain = dns.name.from_text('e164.arpa.')
+public_enum_domain = dns.name.from_text("e164.arpa.")
-def from_e164(text: str, origin: Optional[dns.name.Name]=public_enum_domain) -> dns.name.Name:
+def from_e164(
+ text: str, origin: Optional[dns.name.Name] = public_enum_domain
+) -> dns.name.Name:
"""Convert an E.164 number in textual form into a Name object whose
value is the ENUM domain name for that number.
parts = [d for d in text if d.isdigit()]
parts.reverse()
- return dns.name.from_text('.'.join(parts), origin=origin)
+ return dns.name.from_text(".".join(parts), origin=origin)
-def to_e164(name: dns.name.Name, origin: Optional[dns.name.Name]=public_enum_domain,
- want_plus_prefix: bool=True) -> str:
+def to_e164(
+ name: dns.name.Name,
+ origin: Optional[dns.name.Name] = public_enum_domain,
+ want_plus_prefix: bool = True,
+) -> str:
"""Convert an ENUM domain name into an E.164 number.
Note that dnspython does not have any information about preferred
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')
+ raise dns.exception.SyntaxError("non-digit labels in ENUM domain name")
dlabels.reverse()
- text = b''.join(dlabels)
+ text = b"".join(dlabels)
if want_plus_prefix:
- text = b'+' + text
+ text = b"+" + text
return text.decode()
-def query(number: str, domains: Iterable[Union[dns.name.Name, str]],
- resolver: Optional[dns.resolver.Resolver]=None) -> dns.resolver.Answer:
+def query(
+ number: str,
+ domains: Iterable[Union[dns.name.Name, str]],
+ resolver: Optional[dns.resolver.Resolver] = None,
+) -> dns.resolver.Answer:
"""Look for NAPTR RRs for the specified number in the specified domains.
e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
domain = dns.name.from_text(domain)
qname = dns.e164.from_e164(number, domain)
try:
- return resolver.resolve(qname, 'NAPTR')
+ return resolver.resolve(qname, "NAPTR")
except dns.resolver.NXDOMAIN as e:
e_nx += e
raise e_nx
"""
self.otype = OptionType.make(otype)
- def to_wire(self, file: Optional[Any]=None) -> Optional[bytes]:
+ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
"""Convert an option to wire format.
Returns a ``bytes`` or ``None``.
raise NotImplementedError # pragma: no cover
@classmethod
- def from_wire_parser(cls, otype: OptionType, parser: 'dns.wire.Parser') -> 'Option':
+ def from_wire_parser(cls, otype: OptionType, parser: "dns.wire.Parser") -> "Option":
"""Build an EDNS option object from wire format.
*otype*, a ``dns.edns.OptionType``, is the option type.
return self._cmp(other) != 0
def __lt__(self, other):
- if not isinstance(other, Option) or \
- self.otype != other.otype:
+ if not isinstance(other, Option) or 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:
+ if not isinstance(other, Option) or 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:
+ if not isinstance(other, Option) or 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:
+ if not isinstance(other, Option) or self.otype != other.otype:
return NotImplemented
return self._cmp(other) > 0
super().__init__(otype)
self.data = dns.rdata.Rdata._as_bytes(data, True)
- def to_wire(self, file: Optional[Any]=None) -> Optional[bytes]:
+ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
if file:
file.write(self.data)
return None
return "Generic %d" % self.otype
@classmethod
- def from_wire_parser(cls, otype: Union[OptionType, str], parser: 'dns.wire.Parser') -> Option:
+ def from_wire_parser(
+ cls, otype: Union[OptionType, str], parser: "dns.wire.Parser"
+ ) -> Option:
return cls(otype, parser.get_remaining())
class ECSOption(Option): # lgtm[py/missing-equals]
"""EDNS Client Subnet (ECS, RFC7871)"""
- def __init__(self, address: str, srclen: Optional[int]=None, scopelen: int=0):
+ def __init__(self, address: str, srclen: Optional[int] = None, scopelen: int = 0):
"""*address*, a ``str``, is the client address information.
*srclen*, an ``int``, the source prefix length, which is the
srclen = dns.rdata.Rdata._as_int(srclen, 0, 32)
scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 32)
else: # pragma: no cover (this will never happen)
- raise ValueError('Bad address family')
+ raise ValueError("Bad address family")
assert srclen is not None
self.address = address
self.addrdata = addrdata[:nbytes]
nbits = srclen % 8
if nbits != 0:
- last = struct.pack('B',
- ord(self.addrdata[-1:]) & (0xff << (8 - nbits)))
+ last = struct.pack("B", ord(self.addrdata[-1:]) & (0xFF << (8 - nbits)))
self.addrdata = self.addrdata[:-1] + last
def to_text(self) -> str:
- return "ECS {}/{} scope/{}".format(self.address, self.srclen,
- self.scopelen)
+ return "ECS {}/{} scope/{}".format(self.address, self.srclen, self.scopelen)
@staticmethod
def from_text(text: str) -> Option:
>>> # it understands results from `dns.edns.ECSOption.to_text()`
>>> dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32')
"""
- optional_prefix = 'ECS'
+ optional_prefix = "ECS"
tokens = text.split()
ecs_text = None
if len(tokens) == 1:
ecs_text = tokens[1]
else:
raise ValueError('could not parse ECS from "{}"'.format(text))
- n_slashes = ecs_text.count('/')
+ n_slashes = ecs_text.count("/")
if n_slashes == 1:
- address, tsrclen = ecs_text.split('/')
- tscope = '0'
+ address, tsrclen = ecs_text.split("/")
+ tscope = "0"
elif n_slashes == 2:
- address, tsrclen, tscope = ecs_text.split('/')
+ address, tsrclen, tscope = ecs_text.split("/")
else:
raise ValueError('could not parse ECS from "{}"'.format(text))
try:
scope = int(tscope)
except ValueError:
- raise ValueError('invalid scope ' +
- '"{}": scope must be an integer'.format(tscope))
+ raise ValueError(
+ "invalid scope " + '"{}": scope must be an integer'.format(tscope)
+ )
try:
srclen = int(tsrclen)
except ValueError:
- raise ValueError('invalid srclen ' +
- '"{}": srclen must be an integer'.format(tsrclen))
+ raise ValueError(
+ "invalid srclen " + '"{}": srclen must be an integer'.format(tsrclen)
+ )
return ECSOption(address, srclen, scope)
- def to_wire(self, file: Optional[Any]=None) -> Optional[bytes]:
- value = (struct.pack('!HBB', self.family, self.srclen, self.scopelen) +
- self.addrdata)
+ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
+ value = (
+ struct.pack("!HBB", self.family, self.srclen, self.scopelen) + self.addrdata
+ )
if file:
file.write(value)
return None
return value
@classmethod
- def from_wire_parser(cls, otype: Union[OptionType, str], parser: 'dns.wire.Parser') -> Option:
- family, src, scope = parser.get_struct('!HBB')
+ def from_wire_parser(
+ cls, otype: Union[OptionType, str], parser: "dns.wire.Parser"
+ ) -> Option:
+ family, src, scope = parser.get_struct("!HBB")
addrlen = int(math.ceil(src / 8.0))
prefix = parser.get_bytes(addrlen)
if family == 1:
pad = 4 - addrlen
- addr = dns.ipv4.inet_ntoa(prefix + b'\x00' * pad)
+ addr = dns.ipv4.inet_ntoa(prefix + b"\x00" * pad)
elif family == 2:
pad = 16 - addrlen
- addr = dns.ipv6.inet_ntoa(prefix + b'\x00' * pad)
+ addr = dns.ipv6.inet_ntoa(prefix + b"\x00" * pad)
else:
- raise ValueError('unsupported family')
+ raise ValueError("unsupported family")
return cls(addr, src, scope)
class EDEOption(Option): # lgtm[py/missing-equals]
"""Extended DNS Error (EDE, RFC8914)"""
- def __init__(self, code: Union[EDECode, str], text: Optional[str]=None):
+ def __init__(self, code: Union[EDECode, str], text: Optional[str] = None):
"""*code*, a ``dns.edns.EDECode`` or ``str``, the info code of the
extended error.
self.code = EDECode.make(code)
if text is not None and not isinstance(text, str):
- raise ValueError('text must be string or None')
+ raise ValueError("text must be string or None")
self.text = text
def to_text(self) -> str:
- output = f'EDE {self.code}'
+ output = f"EDE {self.code}"
if self.text is not None:
- output += f': {self.text}'
+ output += f": {self.text}"
return output
- def to_wire(self, file: Optional[Any]=None) -> Optional[bytes]:
- value = struct.pack('!H', self.code)
+ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
+ value = struct.pack("!H", self.code)
if self.text is not None:
- value += self.text.encode('utf8')
+ value += self.text.encode("utf8")
if file:
file.write(value)
return value
@classmethod
- def from_wire_parser(cls, otype: Union[OptionType, str], parser: 'dns.wire.Parser') -> Option:
+ def from_wire_parser(
+ cls, otype: Union[OptionType, str], parser: "dns.wire.Parser"
+ ) -> Option:
the_code = EDECode.make(parser.get_uint16())
text = parser.get_remaining()
if text:
if text[-1] == 0: # text MAY be null-terminated
text = text[:-1]
- btext = text.decode('utf8')
+ btext = text.decode("utf8")
else:
btext = None
return cls
-def option_from_wire_parser(otype: Union[OptionType, str], parser: 'dns.wire.Parser') -> Option:
+def option_from_wire_parser(
+ otype: Union[OptionType, str], parser: "dns.wire.Parser"
+) -> Option:
"""Build an EDNS option object from wire format.
*otype*, an ``int``, is the option type.
return cls.from_wire_parser(otype, parser)
-def option_from_wire(otype: Union[OptionType, str], wire: bytes, current: int, olen: int) -> Option:
+def option_from_wire(
+ otype: Union[OptionType, str], wire: bytes, current: int, olen: int
+) -> Option:
"""Build an EDNS option object from wire format.
*otype*, an ``int``, is the option type.
with parser.restrict_to(olen):
return option_from_wire_parser(otype, parser)
+
def register_type(implementation: Any, otype: OptionType) -> None:
"""Register the implementation of an option type.
_type_to_class[otype] = implementation
+
### BEGIN generated OptionType constants
NSID = OptionType.NSID
import hashlib
import random
import time
+
try:
import threading as _threading
except ImportError: # pragma: no cover
- import dummy_threading as _threading # type: ignore
+ import dummy_threading as _threading # type: ignore
class EntropyPool:
# leaving this code doesn't hurt anything as the library code
# is used if present.
- def __init__(self, seed: Optional[bytes]=None):
+ def __init__(self, seed: Optional[bytes] = None):
self.pool_index = 0
self.digest: Optional[bytearray] = None
self.next_byte = 0
self.lock = _threading.Lock()
self.hash = hashlib.sha1()
self.hash_len = 20
- self.pool = bytearray(b'\0' * self.hash_len)
+ self.pool = bytearray(b"\0" * self.hash_len)
if seed is not None:
self._stir(seed)
self.seeded = True
for c in entropy:
if self.pool_index == self.hash_len:
self.pool_index = 0
- b = c & 0xff
+ b = c & 0xFF
self.pool[self.pool_index] ^= b
self.pool_index += 1
seed = os.urandom(16)
except Exception: # pragma: no cover
try:
- with open('/dev/urandom', 'rb', 0) as r:
+ with open("/dev/urandom", "rb", 0) as r:
seed = r.read(16)
except Exception:
seed = str(time.time()).encode()
def random_between(self, first: int, last: int) -> int:
size = last - first + 1
if size > 4294967296:
- raise ValueError('too big')
+ raise ValueError("too big")
if size > 65536:
rand = self.random_32
max = 4294967295
max = 255
return first + size * rand() // (max + 1)
+
pool = EntropyPool()
system_random: Optional[Any]
except Exception: # pragma: no cover
system_random = None
+
def random_16() -> int:
if system_random is not None:
return system_random.randrange(0, 65536)
else:
return pool.random_16()
+
def between(first: int, last: int) -> int:
if system_random is not None:
return system_random.randrange(first, last + 1)
import enum
+
class IntEnum(enum.IntEnum):
@classmethod
def _check_value(cls, value):
except KeyError:
pass
prefix = cls._prefix()
- if text.startswith(prefix) and text[len(prefix):].isdigit():
- value = int(text[len(prefix):])
+ if text.startswith(prefix) and text[len(prefix) :].isdigit():
+ value = int(text[len(prefix) :])
cls._check_value(value)
try:
return cls(value)
@classmethod
def _prefix(cls):
- return ''
+ return ""
@classmethod
def _unknown_exception_class(cls):
For sanity we do not allow to mix old and new behavior."""
if args or kwargs:
- assert bool(args) != bool(kwargs), \
- 'keyword arguments are mutually exclusive with positional args'
+ assert bool(args) != bool(
+ kwargs
+ ), "keyword arguments are mutually exclusive with positional args"
def _check_kwargs(self, **kwargs):
if kwargs:
- assert set(kwargs.keys()) == self.supp_kwargs, \
- 'following set of keyword args is required: %s' % (
- self.supp_kwargs)
+ assert (
+ set(kwargs.keys()) == self.supp_kwargs
+ ), "following set of keyword args is required: %s" % (self.supp_kwargs)
return kwargs
def _fmt_kwargs(self, **kwargs):
class Timeout(DNSException):
"""The DNS operation timed out."""
- supp_kwargs = {'timeout'}
+
+ supp_kwargs = {"timeout"}
fmt = "The DNS operation timed out after {timeout:.3f} seconds"
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
- if exc_type is not None and not isinstance(exc_val,
- self.exception_class):
+ if exc_type is not None and not isinstance(exc_val, self.exception_class):
raise self.exception_class(str(exc_val)) from exc_val
return False
# Standard DNS flags
+
class Flag(enum.IntFlag):
#: Query Response
QR = 0x8000
# EDNS flags
+
class EDNSFlag(enum.IntFlag):
#: DNSSEC answer OK
DO = 0x8000
for k, v in enum_class.__members__.items():
if flags & v != 0:
text_flags.append(k)
- return ' '.join(text_flags)
+ return " ".join(text_flags)
def from_text(text: str) -> int:
return _to_text(flags, EDNSFlag)
+
### BEGIN generated Flag constants
QR = Flag.QR
import dns
+
def from_text(text: str) -> Tuple[int, int, int]:
"""Convert the text form of a range in a ``$GENERATE`` statement to an
integer.
start = -1
stop = -1
step = 1
- cur = ''
+ cur = ""
state = 0
# state 0 1 2
# x - y / z
- if text and text[0] == '-':
+ if text and text[0] == "-":
raise dns.exception.SyntaxError("Start cannot be a negative number")
for c in text:
- if c == '-' and state == 0:
+ if c == "-" and state == 0:
start = int(cur)
- cur = ''
+ cur = ""
state = 1
- elif c == '/':
+ elif c == "/":
stop = int(cur)
- cur = ''
+ cur = ""
state = 2
elif c.isdigit():
cur += c
assert step >= 1
assert start >= 0
if start > stop:
- raise dns.exception.SyntaxError('start must be <= stop')
+ raise dns.exception.SyntaxError("start must be <= stop")
return (start, stop, step)
@immutable
class Dict(collections.abc.Mapping): # lgtm[py/missing-equals]
- def __init__(self, dictionary: Any, no_copy: bool=False):
+ def __init__(self, dictionary: Any, no_copy: bool = False):
"""Make an immutable dictionary from the specified dictionary.
If *no_copy* is `True`, then *dictionary* will be wrapped instead
h = 0
for key in sorted(self._odict.keys()):
h ^= hash(key)
- object.__setattr__(self, '_hash', h)
+ object.__setattr__(self, "_hash", h)
# this does return an int, but pylint doesn't figure that out
return self._hash
return False
-def low_level_address_tuple(high_tuple: Tuple[str, int], af: Optional[int]=None) -> Any:
+def low_level_address_tuple(
+ high_tuple: Tuple[str, int], af: Optional[int] = None
+) -> Any:
"""Given a "high-level" address tuple, i.e.
an (address, port) return the appropriate "low-level" address tuple
suitable for use in socket calls.
if af == AF_INET:
return (address, port)
elif af == AF_INET6:
- i = address.find('%')
+ i = address.find("%")
if i < 0:
# no scope, shortcut!
return (address, port, 0, 0)
# try to avoid getaddrinfo()
addrpart = address[:i]
- scope = address[i + 1:]
+ scope = address[i + 1 :]
if scope.isdigit():
return (addrpart, port, 0, int(scope))
try:
((*_, tup), *_) = socket.getaddrinfo(address, port, flags=ai_flags)
return tup
else:
- raise NotImplementedError(f'unknown address family {af}')
+ raise NotImplementedError(f"unknown address family {af}")
import dns.exception
+
def inet_ntoa(address: bytes) -> str:
"""Convert an IPv4 address in binary form to text form.
if len(address) != 4:
raise dns.exception.SyntaxError
- return ('%u.%u.%u.%u' % (address[0], address[1],
- address[2], address[3]))
+ return "%u.%u.%u.%u" % (address[0], address[1], address[2], address[3])
+
def inet_aton(text: Union[str, bytes]) -> bytes:
"""Convert an IPv4 address in text form to binary form.
btext = text.encode()
else:
btext = text
- parts = btext.split(b'.')
+ parts = btext.split(b".")
if len(parts) != 4:
raise dns.exception.SyntaxError
for part in parts:
if not part.isdigit():
raise dns.exception.SyntaxError
- if len(part) > 1 and part[0] == ord('0'):
+ if len(part) > 1 and part[0] == ord("0"):
# No leading zeros
raise dns.exception.SyntaxError
try:
b = [int(part) for part in parts]
- return struct.pack('BBBB', *b)
+ return struct.pack("BBBB", *b)
except Exception:
raise dns.exception.SyntaxError
import dns.exception
import dns.ipv4
-_leading_zero = re.compile(r'0+([0-9a-f]+)')
+_leading_zero = re.compile(r"0+([0-9a-f]+)")
+
def inet_ntoa(address: bytes) -> str:
"""Convert an IPv6 address in binary form to text form.
i = 0
l = len(hex)
while i < l:
- chunk = hex[i:i + 4].decode()
+ chunk = hex[i : i + 4].decode()
# strip leading zeros. we do this with an re instead of
# with lstrip() because lstrip() didn't support chars until
# python 2.2.2
start = -1
last_was_zero = False
for i in range(8):
- if chunks[i] != '0':
+ if chunks[i] != "0":
if last_was_zero:
end = i
current_len = end - start
best_start = start
best_len = current_len
if best_len > 1:
- if best_start == 0 and \
- (best_len == 6 or
- best_len == 5 and chunks[5] == 'ffff'):
+ if best_start == 0 and (best_len == 6 or best_len == 5 and chunks[5] == "ffff"):
# We have an embedded IPv4 address
if best_len == 6:
- prefix = '::'
+ prefix = "::"
else:
- prefix = '::ffff:'
+ prefix = "::ffff:"
thex = prefix + dns.ipv4.inet_ntoa(address[12:])
else:
- thex = ':'.join(chunks[:best_start]) + '::' + \
- ':'.join(chunks[best_start + best_len:])
+ thex = (
+ ":".join(chunks[:best_start])
+ + "::"
+ + ":".join(chunks[best_start + best_len :])
+ )
else:
- thex = ':'.join(chunks)
+ thex = ":".join(chunks)
return thex
-_v4_ending = re.compile(br'(.*):(\d+\.\d+\.\d+\.\d+)$')
-_colon_colon_start = re.compile(br'::.*')
-_colon_colon_end = re.compile(br'.*::$')
-def inet_aton(text: Union[str, bytes], ignore_scope: bool=False) -> bytes:
+_v4_ending = re.compile(rb"(.*):(\d+\.\d+\.\d+\.\d+)$")
+_colon_colon_start = re.compile(rb"::.*")
+_colon_colon_end = re.compile(rb".*::$")
+
+
+def inet_aton(text: Union[str, bytes], ignore_scope: bool = False) -> bytes:
"""Convert an IPv6 address in text form to binary form.
*text*, a ``str``, the IPv6 address in textual form.
btext = text
if ignore_scope:
- parts = btext.split(b'%')
+ parts = btext.split(b"%")
l = len(parts)
if l == 2:
btext = parts[0]
elif l > 2:
raise dns.exception.SyntaxError
- if btext == b'':
+ if btext == b"":
raise dns.exception.SyntaxError
- elif btext.endswith(b':') and not btext.endswith(b'::'):
+ elif btext.endswith(b":") and not btext.endswith(b"::"):
raise dns.exception.SyntaxError
- elif btext.startswith(b':') and not btext.startswith(b'::'):
+ elif btext.startswith(b":") and not btext.startswith(b"::"):
raise dns.exception.SyntaxError
- elif btext == b'::':
- btext = b'0::'
+ elif btext == b"::":
+ btext = b"0::"
#
# Get rid of the icky dot-quad syntax if we have it.
#
m = _v4_ending.match(btext)
if m is not None:
b = dns.ipv4.inet_aton(m.group(2))
- btext = ("{}:{:02x}{:02x}:{:02x}{:02x}".format(m.group(1).decode(),
- b[0], b[1], b[2],
- b[3])).encode()
+ btext = (
+ "{}:{:02x}{:02x}:{:02x}{:02x}".format(
+ 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>:'
#
# Now canonicalize into 8 chunks of 4 hex digits each
#
- chunks = btext.split(b':')
+ chunks = btext.split(b":")
l = len(chunks)
if l > 8:
raise dns.exception.SyntaxError
seen_empty = False
canonical: List[bytes] = []
for c in chunks:
- if c == b'':
+ if c == b"":
if seen_empty:
raise dns.exception.SyntaxError
seen_empty = True
for _ in range(0, 8 - l + 1):
- canonical.append(b'0000')
+ canonical.append(b"0000")
else:
lc = len(c)
if lc > 4:
raise dns.exception.SyntaxError
if lc != 4:
- c = (b'0' * (4 - lc)) + c
+ c = (b"0" * (4 - lc)) + c
canonical.append(c)
if l < 8 and not seen_empty:
raise dns.exception.SyntaxError
- btext = b''.join(canonical)
+ btext = b"".join(canonical)
#
# Finally we can go to binary.
except (binascii.Error, TypeError):
raise dns.exception.SyntaxError
-_mapped_prefix = b'\x00' * 10 + b'\xff\xff'
+
+_mapped_prefix = b"\x00" * 10 + b"\xff\xff"
+
def is_mapped(address: bytes) -> bool:
"""Is the specified address a mapped IPv4 address?
class Truncated(dns.exception.DNSException):
"""The truncated flag is set."""
- supp_kwargs = {'message'}
+ supp_kwargs = {"message"}
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Returns a ``dns.message.Message``.
"""
- return self.kwargs['message']
+ return self.kwargs["message"]
class NotQueryResponse(dns.exception.DNSException):
class AnswerForNXDOMAIN(dns.exception.DNSException):
"""The rcode is NXDOMAIN but an answer was found."""
+
class NoPreviousName(dns.exception.SyntaxError):
"""No previous name was known."""
class MessageSection(dns.enum.IntEnum):
"""Message sections"""
+
QUESTION = 0
ANSWER = 1
AUTHORITY = 2
DEFAULT_EDNS_PAYLOAD = 1232
MAX_CHAIN = 16
-IndexKeyType = Tuple[int, dns.name.Name, dns.rdataclass.RdataClass,
- dns.rdatatype.RdataType, Optional[dns.rdatatype.RdataType],
- Optional[dns.rdataclass.RdataClass]]
+IndexKeyType = Tuple[
+ int,
+ dns.name.Name,
+ dns.rdataclass.RdataClass,
+ dns.rdatatype.RdataType,
+ Optional[dns.rdatatype.RdataType],
+ Optional[dns.rdataclass.RdataClass],
+]
IndexType = Dict[IndexKeyType, dns.rrset.RRset]
SectionType = Union[int, List[dns.rrset.RRset]]
+
class Message:
"""A DNS message."""
_section_enum = MessageSection
- def __init__(self, id: Optional[int]=None):
+ def __init__(self, id: Optional[int] = None):
if id is None:
self.id = dns.entropy.random_16()
else:
self.request_payload = 0
self.keyring: Any = None
self.tsig: Optional[dns.rrset.RRset] = None
- self.request_mac = b''
+ self.request_mac = b""
self.xfr = False
self.origin: Optional[dns.name.Name] = None
self.tsig_ctx: Optional[Any] = None
@property
def question(self) -> List[dns.rrset.RRset]:
- """ The question section."""
+ """The question section."""
return self.sections[0]
@question.setter
@property
def answer(self) -> List[dns.rrset.RRset]:
- """ The answer section."""
+ """The answer section."""
return self.sections[1]
@answer.setter
@property
def authority(self) -> List[dns.rrset.RRset]:
- """ The authority section."""
+ """The authority section."""
return self.sections[2]
@authority.setter
@property
def additional(self) -> List[dns.rrset.RRset]:
- """ The additional data section."""
+ """The additional data section."""
return self.sections[3]
@additional.setter
self.sections[3] = v
def __repr__(self):
- return '<DNS message, ID ' + repr(self.id) + '>'
+ return "<DNS message, ID " + repr(self.id) + ">"
def __str__(self):
return self.to_text()
- def to_text(self, origin: Optional[dns.name.Name]=None, relativize: bool=True,
- **kw: Dict[str, Any]) -> str:
+ def to_text(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ **kw: Dict[str, Any],
+ ) -> str:
"""Convert the message to text.
The *origin*, *relativize*, and any other keyword
"""
s = io.StringIO()
- s.write('id %d\n' % self.id)
- s.write('opcode %s\n' % dns.opcode.to_text(self.opcode()))
- s.write('rcode %s\n' % dns.rcode.to_text(self.rcode()))
- s.write('flags %s\n' % dns.flags.to_text(self.flags))
+ s.write("id %d\n" % self.id)
+ s.write("opcode %s\n" % dns.opcode.to_text(self.opcode()))
+ s.write("rcode %s\n" % dns.rcode.to_text(self.rcode()))
+ s.write("flags %s\n" % dns.flags.to_text(self.flags))
if self.edns >= 0:
- s.write('edns %s\n' % self.edns)
+ s.write("edns %s\n" % self.edns)
if self.ednsflags != 0:
- s.write('eflags %s\n' %
- dns.flags.edns_to_text(self.ednsflags))
- s.write('payload %d\n' % self.payload)
+ s.write("eflags %s\n" % dns.flags.edns_to_text(self.ednsflags))
+ s.write("payload %d\n" % self.payload)
for opt in self.options:
- s.write('option %s\n' % opt.to_text())
+ s.write("option %s\n" % opt.to_text())
for (name, which) in self._section_enum.__members__.items():
- s.write(f';{name}\n')
+ s.write(f";{name}\n")
for rrset in self.section_from_number(which):
s.write(rrset.to_text(origin, relativize, **kw))
- s.write('\n')
+ s.write("\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
def __ne__(self, other):
return not self.__eq__(other)
- def is_response(self, other: 'Message') -> bool:
+ def is_response(self, other: "Message") -> bool:
"""Is *other*, also a ``dns.message.Message``, a response to this
message?
Returns a ``bool``.
"""
- if other.flags & dns.flags.QR == 0 or \
- self.id != other.id or \
- dns.opcode.from_flags(self.flags) != \
- dns.opcode.from_flags(other.flags):
+ if (
+ other.flags & dns.flags.QR == 0
+ or self.id != other.id
+ or dns.opcode.from_flags(self.flags) != dns.opcode.from_flags(other.flags)
+ ):
return False
- if other.rcode() in {dns.rcode.FORMERR, dns.rcode.SERVFAIL,
- dns.rcode.NOTIMP, dns.rcode.REFUSED}:
+ if other.rcode() in {
+ dns.rcode.FORMERR,
+ dns.rcode.SERVFAIL,
+ dns.rcode.NOTIMP,
+ dns.rcode.REFUSED,
+ }:
# We don't check the question section in these cases if
# the other question section is empty, even though they
# still really ought to have a question section.
for i, our_section in enumerate(self.sections):
if section is our_section:
return self._section_enum(i)
- raise ValueError('unknown section')
+ raise ValueError("unknown section")
def section_from_number(self, number: int) -> List[dns.rrset.RRset]:
"""Return the section list associated with the specified section
section = self._section_enum.make(number)
return self.sections[section]
- def find_rrset(self,
- section: SectionType,
- name: dns.name.Name,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- deleting: Optional[dns.rdataclass.RdataClass]=None,
- create: bool=False,
- force_unique: bool=False) -> dns.rrset.RRset:
+ def find_rrset(
+ self,
+ section: SectionType,
+ name: dns.name.Name,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ deleting: Optional[dns.rdataclass.RdataClass] = None,
+ create: bool = False,
+ force_unique: bool = False,
+ ) -> dns.rrset.RRset:
"""Find the RRset with the given attributes in the specified section.
*section*, an ``int`` section number, or one of the section
return rrset
else:
for rrset in the_section:
- if rrset.full_match(name, rdclass, rdtype, covers,
- deleting):
+ if rrset.full_match(name, rdclass, rdtype, covers, deleting):
return rrset
if not create:
raise KeyError
self.index[key] = rrset
return rrset
- def get_rrset(self,
- section: SectionType,
- name: dns.name.Name,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- deleting: Optional[dns.rdataclass.RdataClass]=None,
- create: bool=False,
- force_unique: bool=False) -> Optional[dns.rrset.RRset]:
+ def get_rrset(
+ self,
+ section: SectionType,
+ name: dns.name.Name,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ deleting: Optional[dns.rdataclass.RdataClass] = None,
+ create: bool = False,
+ force_unique: bool = False,
+ ) -> Optional[dns.rrset.RRset]:
"""Get the RRset with the given attributes in the specified section.
If the RRset is not found, None is returned.
"""
try:
- rrset = self.find_rrset(section, name, rdclass, rdtype, covers,
- deleting, create, force_unique)
+ rrset = self.find_rrset(
+ section, name, rdclass, rdtype, covers, deleting, create, force_unique
+ )
except KeyError:
rrset = None
return rrset
- def to_wire(self, origin: Optional[dns.name.Name]=None, max_size: int=0,
- multi: bool=False, tsig_ctx: Optional[Any]=None, **kw: Dict[str, Any]) -> bytes:
+ def to_wire(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ max_size: int = 0,
+ multi: bool = False,
+ tsig_ctx: Optional[Any] = None,
+ **kw: Dict[str, Any],
+ ) -> bytes:
"""Return a string containing the message in DNS compressed wire
format.
r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
r.write_header()
if self.tsig is not None:
- (new_tsig, ctx) = dns.tsig.sign(r.get_wire(),
- self.keyring,
- self.tsig[0],
- int(time.time()),
- self.request_mac,
- tsig_ctx,
- multi)
+ (new_tsig, ctx) = dns.tsig.sign(
+ r.get_wire(),
+ self.keyring,
+ self.tsig[0],
+ int(time.time()),
+ self.request_mac,
+ tsig_ctx,
+ multi,
+ )
self.tsig.clear()
self.tsig.add(new_tsig)
r.add_rrset(dns.renderer.ADDITIONAL, self.tsig)
return r.get_wire()
@staticmethod
- def _make_tsig(keyname, algorithm, time_signed, fudge, mac, original_id,
- error, other):
- tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.ANY, dns.rdatatype.TSIG,
- algorithm, time_signed, fudge, mac,
- original_id, error, other)
+ def _make_tsig(
+ keyname, algorithm, time_signed, fudge, mac, original_id, error, other
+ ):
+ tsig = dns.rdtypes.ANY.TSIG.TSIG(
+ dns.rdataclass.ANY,
+ dns.rdatatype.TSIG,
+ algorithm,
+ time_signed,
+ fudge,
+ mac,
+ original_id,
+ error,
+ other,
+ )
return dns.rrset.from_rdata(keyname, 0, tsig)
- def use_tsig(self, keyring: Any, keyname: Optional[Union[dns.name.Name, str]]=None,
- fudge: int=300, original_id: Optional[int]=None, tsig_error: int=0,
- other_data: bytes=b'',
- algorithm: Union[dns.name.Name, str]=dns.tsig.default_algorithm) -> None:
+ def use_tsig(
+ self,
+ keyring: Any,
+ keyname: Optional[Union[dns.name.Name, str]] = None,
+ fudge: int = 300,
+ original_id: Optional[int] = None,
+ tsig_error: int = 0,
+ other_data: bytes = b"",
+ algorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm,
+ ) -> None:
"""When sending, a TSIG signature using the specified key
should be added.
self.keyring = key
if original_id is None:
original_id = self.id
- self.tsig = self._make_tsig(keyname, self.keyring.algorithm, 0, fudge,
- b'', original_id, tsig_error, other_data)
+ self.tsig = self._make_tsig(
+ keyname,
+ self.keyring.algorithm,
+ 0,
+ fudge,
+ b"",
+ original_id,
+ tsig_error,
+ other_data,
+ )
@property
def keyname(self) -> Optional[dns.name.Name]:
@staticmethod
def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None):
- opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT,
- options or ())
+ opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT, options or ())
return dns.rrset.from_rdata(dns.name.root, int(flags), opt)
- def use_edns(self, edns: Optional[Union[int, bool]]=0, ednsflags: int=0, payload: int=DEFAULT_EDNS_PAYLOAD,
- request_payload: Optional[int]=None,
- options: Optional[List[dns.edns.Option]]=None) -> None:
+ def use_edns(
+ self,
+ edns: Optional[Union[int, bool]] = 0,
+ ednsflags: int = 0,
+ payload: int = DEFAULT_EDNS_PAYLOAD,
+ request_payload: Optional[int] = None,
+ options: Optional[List[dns.edns.Option]] = None,
+ ) -> None:
"""Configure EDNS behavior.
*edns*, an ``int``, is the EDNS level to use. Specifying
else:
# make sure the EDNS version in ednsflags agrees with edns
ednsflags &= 0xFF00FFFF
- ednsflags |= (edns << 16)
+ ednsflags |= edns << 16
if options is None:
options = []
self.opt = self._make_opt(ednsflags, payload, options)
@property
def edns(self) -> int:
if self.opt:
- return (self.ednsflags & 0xff0000) >> 16
+ return (self.ednsflags & 0xFF0000) >> 16
else:
return -1
else:
return ()
- def want_dnssec(self, wanted: bool=True) -> None:
+ def want_dnssec(self, wanted: bool = True) -> None:
"""Enable or disable 'DNSSEC desired' flag in requests.
*wanted*, a ``bool``. If ``True``, then DNSSEC data is
# pylint: enable=unused-argument
- def _parse_special_rr_header(self, section, count, position,
- name, rdclass, rdtype):
+ def _parse_special_rr_header(self, section, count, position, name, rdclass, rdtype):
if rdtype == dns.rdatatype.OPT:
- if section != MessageSection.ADDITIONAL or self.opt or \
- name != dns.name.root:
+ if (
+ section != MessageSection.ADDITIONAL
+ or self.opt
+ or name != dns.name.root
+ ):
raise BadEDNS
elif rdtype == dns.rdatatype.TSIG:
- if section != MessageSection.ADDITIONAL or \
- rdclass != dns.rdatatype.ANY or \
- position != count - 1:
+ if (
+ section != MessageSection.ADDITIONAL
+ or rdclass != dns.rdatatype.ANY
+ or position != count - 1
+ ):
raise BadTSIG
return (rdclass, rdtype, None, False)
The ``cnames`` attribute is a list of all the CNAME RRSets followed to
get to the canonical name.
"""
- def __init__(self, canonical_name: dns.name.Name, answer: Optional[dns.rrset.RRset],
- minimum_ttl: int, cnames: List[dns.rrset.RRset]):
+
+ def __init__(
+ self,
+ canonical_name: dns.name.Name,
+ answer: Optional[dns.rrset.RRset],
+ minimum_ttl: int,
+ cnames: List[dns.rrset.RRset],
+ ):
self.canonical_name = canonical_name
self.answer = answer
self.minimum_ttl = minimum_ttl
cnames = []
while count < MAX_CHAIN:
try:
- answer = self.find_rrset(self.answer, qname, question.rdclass,
- question.rdtype)
+ answer = self.find_rrset(
+ self.answer, qname, question.rdclass, question.rdtype
+ )
min_ttl = min(min_ttl, answer.ttl)
break
except KeyError:
if question.rdtype != dns.rdatatype.CNAME:
try:
- crrset = self.find_rrset(self.answer, qname,
- question.rdclass,
- dns.rdatatype.CNAME)
+ crrset = self.find_rrset(
+ self.answer, qname, question.rdclass, dns.rdatatype.CNAME
+ )
cnames.append(crrset)
min_ttl = min(min_ttl, crrset.ttl)
for rd in crrset:
# Look for an SOA RR whose owner name is a superdomain
# of qname.
try:
- srrset = self.find_rrset(self.authority, auname,
- question.rdclass,
- dns.rdatatype.SOA)
+ srrset = self.find_rrset(
+ self.authority, auname, question.rdclass, dns.rdatatype.SOA
+ )
min_ttl = min(min_ttl, srrset.ttl, srrset[0].minimum)
break
except KeyError:
raising them.
"""
- def __init__(self, wire, initialize_message, question_only=False,
- one_rr_per_rrset=False, ignore_trailing=False,
- keyring=None, multi=False, continue_on_error=False):
+ def __init__(
+ self,
+ wire,
+ initialize_message,
+ question_only=False,
+ one_rr_per_rrset=False,
+ ignore_trailing=False,
+ keyring=None,
+ multi=False,
+ continue_on_error=False,
+ ):
self.parser = dns.wire.Parser(wire)
self.message = None
self.initialize_message = initialize_message
section = self.message.sections[section_number]
for _ in range(qcount):
qname = self.parser.get_name(self.message.origin)
- (rdtype, rdclass) = self.parser.get_struct('!HH')
- (rdclass, rdtype, _, _) = \
- self.message._parse_rr_header(section_number, qname, rdclass,
- rdtype)
- self.message.find_rrset(section, qname, rdclass, rdtype,
- create=True, force_unique=True)
+ (rdtype, rdclass) = self.parser.get_struct("!HH")
+ (rdclass, rdtype, _, _) = self.message._parse_rr_header(
+ section_number, qname, rdclass, rdtype
+ )
+ self.message.find_rrset(
+ section, qname, rdclass, rdtype, create=True, force_unique=True
+ )
def _add_error(self, e):
self.errors.append(MessageError(e, self.parser.current))
name = absolute_name.relativize(self.message.origin)
else:
name = absolute_name
- (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct('!HHIH')
+ (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct("!HHIH")
if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG):
- (rdclass, rdtype, deleting, empty) = \
- self.message._parse_special_rr_header(section_number,
- count, i, name,
- rdclass, rdtype)
+ (
+ rdclass,
+ rdtype,
+ deleting,
+ empty,
+ ) = self.message._parse_special_rr_header(
+ section_number, count, i, name, rdclass, rdtype
+ )
else:
- (rdclass, rdtype, deleting, empty) = \
- self.message._parse_rr_header(section_number,
- name, rdclass, rdtype)
+ (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header(
+ section_number, name, rdclass, rdtype
+ )
try:
rdata_start = self.parser.current
if empty:
covers = dns.rdatatype.NONE
else:
with self.parser.restrict_to(rdlen):
- rd = dns.rdata.from_wire_parser(rdclass, rdtype,
- self.parser,
- self.message.origin)
+ rd = dns.rdata.from_wire_parser(
+ rdclass, rdtype, self.parser, self.message.origin
+ )
covers = rd.covers()
if self.message.xfr and rdtype == dns.rdatatype.SOA:
force_unique = True
self.message.opt = dns.rrset.from_rdata(name, ttl, rd)
elif rdtype == dns.rdatatype.TSIG:
if self.keyring is None:
- raise UnknownTSIGKey('got signed message without '
- 'keyring')
+ raise UnknownTSIGKey("got signed message without " "keyring")
if isinstance(self.keyring, dict):
key = self.keyring.get(absolute_name)
if isinstance(key, bytes):
if key is None:
raise UnknownTSIGKey("key '%s' unknown" % name)
self.message.keyring = key
- self.message.tsig_ctx = \
- dns.tsig.validate(self.parser.wire,
- key,
- absolute_name,
- rd,
- int(time.time()),
- self.message.request_mac,
- rr_start,
- self.message.tsig_ctx,
- self.multi)
- self.message.tsig = dns.rrset.from_rdata(absolute_name, 0,
- rd)
+ self.message.tsig_ctx = dns.tsig.validate(
+ self.parser.wire,
+ key,
+ absolute_name,
+ rd,
+ int(time.time()),
+ self.message.request_mac,
+ rr_start,
+ self.message.tsig_ctx,
+ self.multi,
+ )
+ self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd)
else:
- rrset = self.message.find_rrset(section, name,
- rdclass, rdtype, covers,
- deleting, True,
- force_unique)
+ rrset = self.message.find_rrset(
+ section,
+ name,
+ rdclass,
+ rdtype,
+ covers,
+ deleting,
+ True,
+ force_unique,
+ )
if rd is not None:
- if ttl > 0x7fffffff:
+ if ttl > 0x7FFFFFFF:
ttl = 0
rrset.add(rd, ttl)
except Exception as e:
if self.parser.remaining() < 12:
raise ShortHeader
- (id, flags, qcount, ancount, aucount, adcount) = \
- self.parser.get_struct('!HHHHHH')
+ (id, flags, qcount, ancount, aucount, adcount) = self.parser.get_struct(
+ "!HHHHHH"
+ )
factory = _message_factory_from_opcode(dns.opcode.from_flags(flags))
self.message = factory(id=id)
self.message.flags = dns.flags.Flag(flags)
self.initialize_message(self.message)
- self.one_rr_per_rrset = \
- self.message._get_one_rr_per_rrset(self.one_rr_per_rrset)
+ self.one_rr_per_rrset = self.message._get_one_rr_per_rrset(
+ self.one_rr_per_rrset
+ )
try:
self._get_question(MessageSection.QUESTION, qcount)
if self.question_only:
self._get_section(MessageSection.ADDITIONAL, adcount)
if not self.ignore_trailing and self.parser.remaining() != 0:
raise TrailingJunk
- if self.multi and self.message.tsig_ctx and \
- not self.message.had_tsig:
+ if self.multi and self.message.tsig_ctx and not self.message.had_tsig:
self.message.tsig_ctx.update(self.parser.wire)
except Exception as e:
if self.continue_on_error:
return self.message
-def from_wire(wire: bytes, keyring: Optional[Any]=None, request_mac: Optional[bytes]=b'',
- xfr: bool=False, origin: Optional[dns.name.Name]=None,
- tsig_ctx: Optional[Union[dns.tsig.HMACTSig, dns.tsig.GSSTSig]]=None,
- multi: bool=False, question_only: bool=False, one_rr_per_rrset: bool=False,
- ignore_trailing: bool=False, raise_on_truncation: bool=False,
- continue_on_error: bool=False) -> Message:
+def from_wire(
+ wire: bytes,
+ keyring: Optional[Any] = None,
+ request_mac: Optional[bytes] = b"",
+ xfr: bool = False,
+ origin: Optional[dns.name.Name] = None,
+ tsig_ctx: Optional[Union[dns.tsig.HMACTSig, dns.tsig.GSSTSig]] = None,
+ multi: bool = False,
+ question_only: bool = False,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ raise_on_truncation: bool = False,
+ continue_on_error: bool = False,
+) -> Message:
"""Convert a DNS wire format message into a message object.
- *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use if the
- message is signed.
+ *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use if the message
+ is signed.
- *request_mac*, a ``bytes`` or ``None``. If the message is a response to a TSIG-signed
- request, *request_mac* should be set to the MAC of that request.
+ *request_mac*, a ``bytes`` or ``None``. If the message is a response to a
+ TSIG-signed request, *request_mac* should be set to the MAC of that request.
- *xfr*, a ``bool``, should be set to ``True`` if this message is part of a
- zone transfer.
+ *xfr*, a ``bool``, should be set to ``True`` if this message is part of a zone
+ transfer.
*origin*, a ``dns.name.Name`` or ``None``. If the message is part of a zone
- transfer, *origin* should be the origin name of the zone. If not ``None``,
- names will be relativized to the origin.
+ transfer, *origin* should be the origin name of the zone. If not ``None``, names
+ will be relativized to the origin.
- *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the
- ongoing TSIG context, used when validating zone transfers.
+ *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the ongoing TSIG
+ context, used when validating zone transfers.
- *multi*, a ``bool``, should be set to ``True`` if this message is part of a
- multiple message sequence.
+ *multi*, a ``bool``, should be set to ``True`` if this message is part of a multiple
+ message sequence.
- *question_only*, a ``bool``. If ``True``, read only up to the end of the
- question section.
+ *question_only*, a ``bool``. If ``True``, read only up to the end of the question
+ section.
- *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
- RRset.
+ *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset.
- *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of
- the message.
+ *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the
+ message.
- *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if the
- TC bit is set.
+ *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if the TC bit is
+ set.
- *continue_on_error*, a ``bool``. If ``True``, try to continue parsing even
- if errors occur. Erroneous rdata will be ignored. Errors will be
- accumulated as a list of MessageError objects in the message's ``errors``
- attribute. This option is recommended only for DNS analysis tools, or for
- use in a server as part of an error handling path. The default is
- ``False``.
+ *continue_on_error*, a ``bool``. If ``True``, try to continue parsing even if
+ errors occur. Erroneous rdata will be ignored. Errors will be accumulated as a
+ list of MessageError objects in the message's ``errors`` attribute. This option is
+ recommended only for DNS analysis tools, or for use in a server as part of an error
+ handling path. The default is ``False``.
- Raises ``dns.message.ShortHeader`` if the message is less than 12 octets
- long.
+ Raises ``dns.message.ShortHeader`` if the message is less than 12 octets long.
- Raises ``dns.message.TrailingJunk`` if there were octets in the message past
- the end of the proper DNS message, and *ignore_trailing* is ``False``.
+ Raises ``dns.message.TrailingJunk`` if there were octets in the message past the end
+ of the proper DNS message, and *ignore_trailing* is ``False``.
Raises ``dns.message.BadEDNS`` if an OPT record was in the wrong section, or
occurred more than once.
- Raises ``dns.message.BadTSIG`` if a TSIG record was not the last record of
- the additional data section.
+ Raises ``dns.message.BadTSIG`` if a TSIG record was not the last record of the
+ additional data section.
- Raises ``dns.message.Truncated`` if the TC flag is set and
- *raise_on_truncation* is ``True``.
+ Raises ``dns.message.Truncated`` if the TC flag is set and *raise_on_truncation* is
+ ``True``.
Returns a ``dns.message.Message``.
"""
# We permit None for request_mac solely for backwards compatibility
if request_mac is None:
- request_mac = b''
+ request_mac = b""
def initialize_message(message):
message.request_mac = request_mac
message.origin = origin
message.tsig_ctx = tsig_ctx
- reader = _WireReader(wire, initialize_message, question_only,
- one_rr_per_rrset, ignore_trailing, keyring, multi,
- continue_on_error)
+ reader = _WireReader(
+ wire,
+ initialize_message,
+ question_only,
+ one_rr_per_rrset,
+ ignore_trailing,
+ keyring,
+ multi,
+ continue_on_error,
+ )
try:
m = reader.read()
except dns.exception.FormError:
- if reader.message and (reader.message.flags & dns.flags.TC) and \
- raise_on_truncation:
+ if (
+ reader.message
+ and (reader.message.flags & dns.flags.TC)
+ and raise_on_truncation
+ ):
raise Truncated(message=reader.message)
else:
raise
relativize_to: the origin to relativize to.
"""
- def __init__(self, text, idna_codec, one_rr_per_rrset=False,
- origin=None, relativize=True, relativize_to=None):
+ def __init__(
+ self,
+ text,
+ idna_codec,
+ one_rr_per_rrset=False,
+ origin=None,
+ relativize=True,
+ relativize_to=None,
+ ):
self.message = None
self.tok = dns.tokenizer.Tokenizer(text, idna_codec=idna_codec)
self.last_name = None
token = self.tok.get()
what = token.value
- if what == 'id':
+ if what == "id":
self.id = self.tok.get_int()
- elif what == 'flags':
+ elif what == "flags":
while True:
token = self.tok.get()
if not token.is_identifier():
self.tok.unget(token)
break
self.flags = self.flags | dns.flags.from_text(token.value)
- elif what == 'edns':
+ elif what == "edns":
self.edns = self.tok.get_int()
self.ednsflags = self.ednsflags | (self.edns << 16)
- elif what == 'eflags':
+ elif what == "eflags":
if self.edns < 0:
self.edns = 0
while True:
if not token.is_identifier():
self.tok.unget(token)
break
- self.ednsflags = self.ednsflags | \
- dns.flags.edns_from_text(token.value)
- elif what == 'payload':
+ self.ednsflags = self.ednsflags | dns.flags.edns_from_text(token.value)
+ elif what == "payload":
self.payload = self.tok.get_int()
if self.edns < 0:
self.edns = 0
- elif what == 'opcode':
+ elif what == "opcode":
text = self.tok.get_string()
self.opcode = dns.opcode.from_text(text)
self.flags = self.flags | dns.opcode.to_flags(self.opcode)
- elif what == 'rcode':
+ elif what == "rcode":
text = self.tok.get_string()
self.rcode = dns.rcode.from_text(text)
else:
section = self.message.sections[section_number]
token = self.tok.get(want_leading=True)
if not token.is_whitespace():
- self.last_name = self.tok.as_name(token, self.message.origin,
- self.relativize,
- self.relativize_to)
+ self.last_name = self.tok.as_name(
+ token, self.message.origin, self.relativize, self.relativize_to
+ )
name = self.last_name
if name is None:
raise NoPreviousName
rdclass = dns.rdataclass.IN
# Type
rdtype = dns.rdatatype.from_text(token.value)
- (rdclass, rdtype, _, _) = \
- self.message._parse_rr_header(section_number, name, rdclass, rdtype)
- self.message.find_rrset(section, name, rdclass, rdtype, create=True,
- force_unique=True)
+ (rdclass, rdtype, _, _) = self.message._parse_rr_header(
+ section_number, name, rdclass, rdtype
+ )
+ self.message.find_rrset(
+ section, name, rdclass, rdtype, create=True, force_unique=True
+ )
self.tok.get_eol()
def _rr_line(self, section_number):
# Name
token = self.tok.get(want_leading=True)
if not token.is_whitespace():
- self.last_name = self.tok.as_name(token, self.message.origin,
- self.relativize,
- self.relativize_to)
+ self.last_name = self.tok.as_name(
+ token, self.message.origin, self.relativize, self.relativize_to
+ )
name = self.last_name
if name is None:
raise NoPreviousName
rdclass = dns.rdataclass.IN
# Type
rdtype = dns.rdatatype.from_text(token.value)
- (rdclass, rdtype, deleting, empty) = \
- self.message._parse_rr_header(section_number, name, rdclass, rdtype)
+ (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header(
+ section_number, name, rdclass, rdtype
+ )
token = self.tok.get()
if empty and not token.is_eol_or_eof():
raise dns.exception.SyntaxError
raise dns.exception.UnexpectedEnd
if not token.is_eol_or_eof():
self.tok.unget(token)
- rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
- self.message.origin, self.relativize,
- self.relativize_to)
+ rd = dns.rdata.from_text(
+ rdclass,
+ rdtype,
+ self.tok,
+ self.message.origin,
+ self.relativize,
+ self.relativize_to,
+ )
covers = rd.covers()
else:
rd = None
covers = dns.rdatatype.NONE
- rrset = self.message.find_rrset(section, name,
- rdclass, rdtype, covers,
- deleting, True, self.one_rr_per_rrset)
+ rrset = self.message.find_rrset(
+ section,
+ name,
+ rdclass,
+ rdtype,
+ covers,
+ deleting,
+ True,
+ self.one_rr_per_rrset,
+ )
if rd is not None:
rrset.add(rd, ttl)
break
if token.is_comment():
u = token.value.upper()
- if u == 'HEADER':
+ if u == "HEADER":
line_method = self._header_line
if self.message:
# use the one we just created.
if not self.message:
self.message = message
- self.one_rr_per_rrset = \
- message._get_one_rr_per_rrset(self.one_rr_per_rrset)
+ self.one_rr_per_rrset = message._get_one_rr_per_rrset(
+ self.one_rr_per_rrset
+ )
if section_number == MessageSection.QUESTION:
line_method = self._question_line
else:
return self.message
-def from_text(text: str, idna_codec: Optional[dns.name.IDNACodec]=None,
- one_rr_per_rrset: bool=False, origin: Optional[dns.name.Name]=None,
- relativize: bool=True, relativize_to: Optional[dns.name.Name]=None) -> Message:
+def from_text(
+ text: str,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ one_rr_per_rrset: bool = False,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+) -> Message:
"""Convert the text format message into a message object.
The reader stops after reading the first blank line in the input to
# since it's an implementation detail. The official file
# interface is from_file().
- reader = _TextReader(text, idna_codec, one_rr_per_rrset, origin,
- relativize, relativize_to)
+ reader = _TextReader(
+ text, idna_codec, one_rr_per_rrset, origin, relativize, relativize_to
+ )
return reader.read()
-def from_file(f: Any, idna_codec: Optional[dns.name.IDNACodec]=None, one_rr_per_rrset: bool=False) -> Message:
+def from_file(
+ f: Any,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ one_rr_per_rrset: bool = False,
+) -> Message:
"""Read the next text format message from the specified file.
Message blocks are separated by a single blank line.
assert False # for mypy lgtm[py/unreachable-statement]
-def make_query(qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- use_edns: Optional[Union[int, bool]]=None,
- want_dnssec: bool=False, ednsflags: Optional[int]=None, payload: Optional[int]=None,
- request_payload: Optional[int]=None, options: Optional[List[dns.edns.Option]]=None,
- idna_codec: Optional[dns.name.IDNACodec]=None, id: Optional[int]=None,
- flags: int=dns.flags.RD) -> QueryMessage:
+def make_query(
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ use_edns: Optional[Union[int, bool]] = None,
+ want_dnssec: bool = False,
+ ednsflags: Optional[int] = None,
+ payload: Optional[int] = None,
+ request_payload: Optional[int] = None,
+ options: Optional[List[dns.edns.Option]] = None,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ id: Optional[int] = None,
+ flags: int = dns.flags.RD,
+) -> QueryMessage:
"""Make a query message.
The query name, type, and class may all be specified either
the_rdclass = dns.rdataclass.RdataClass.make(rdclass)
m = QueryMessage(id=id)
m.flags = dns.flags.Flag(flags)
- m.find_rrset(m.question, qname, the_rdclass, the_rdtype, create=True,
- force_unique=True)
+ m.find_rrset(
+ m.question, qname, the_rdclass, the_rdtype, create=True, force_unique=True
+ )
# only pass keywords on to use_edns if they have been set to a
# non-None value. Setting a field will turn EDNS on if it hasn't
# been configured.
kwargs: Dict[str, Any] = {}
if ednsflags is not None:
- kwargs['ednsflags'] = ednsflags
+ kwargs["ednsflags"] = ednsflags
if payload is not None:
- kwargs['payload'] = payload
+ kwargs["payload"] = payload
if request_payload is not None:
- kwargs['request_payload'] = request_payload
+ kwargs["request_payload"] = request_payload
if options is not None:
- kwargs['options'] = options
+ kwargs["options"] = options
if kwargs and use_edns is None:
use_edns = 0
- kwargs['edns'] = use_edns
+ kwargs["edns"] = use_edns
m.use_edns(**kwargs)
m.want_dnssec(want_dnssec)
return m
-def make_response(query: Message, recursion_available: bool=False, our_payload: int=8192,
- fudge: int=300, tsig_error: int=0) -> Message:
+def make_response(
+ query: Message,
+ recursion_available: bool = False,
+ our_payload: int = 8192,
+ fudge: int = 300,
+ tsig_error: int = 0,
+) -> Message:
"""Make a message which is a response for the specified query.
The message returned is really a response skeleton; it has all
of the infrastructure required of a response, but none of the
"""
if query.flags & dns.flags.QR:
- raise dns.exception.FormError('specified query message is not a query')
+ raise dns.exception.FormError("specified query message is not a query")
factory = _message_factory_from_opcode(query.opcode())
response = factory(id=query.id)
response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
if query.edns >= 0:
response.use_edns(0, 0, our_payload, query.payload)
if query.had_tsig:
- response.use_tsig(query.keyring, query.keyname, fudge, None,
- tsig_error, b'', query.keyalgorithm)
+ response.use_tsig(
+ query.keyring,
+ query.keyname,
+ fudge,
+ None,
+ tsig_error,
+ b"",
+ query.keyalgorithm,
+ )
response.request_mac = query.mac
return response
+
### BEGIN generated MessageSection constants
QUESTION = MessageSection.QUESTION
import copy
import struct
-import encodings.idna # type: ignore
+import encodings.idna # type: ignore
+
try:
- import idna # type: ignore
+ import idna # type: ignore
+
have_idna_2008 = True
except ImportError: # pragma: no cover
have_idna_2008 = False
import dns.immutable
-CompressType = Dict['Name', int]
+CompressType = Dict["Name", int]
class NameRelation(dns.enum.IntEnum):
"""An attempt was made to get the parent of the root name
or the empty name."""
+
class NoIDNA2008(dns.exception.DNSException):
"""IDNA 2008 processing was requested but the idna module is not
available."""
class IDNAException(dns.exception.DNSException):
"""IDNA processing raised an exception."""
- supp_kwargs = {'idna_exception'}
+ supp_kwargs = {"idna_exception"}
fmt = "IDNA processing exception: {idna_exception}"
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
_escaped = b'"().;\\@$'
_escaped_text = '"().;\\@$'
+
def _escapify(label: Union[bytes, str]) -> str:
"""Escape the characters in label which need it.
@returns: the escaped string
if isinstance(label, bytes):
# Ordinary DNS label mode. Escape special characters and values
# < 0x20 or > 0x7f.
- text = ''
+ text = ""
for c in label:
if c in _escaped:
- text += '\\' + chr(c)
+ text += "\\" + chr(c)
elif c > 0x20 and c < 0x7F:
text += chr(c)
else:
- text += '\\%03d' % c
+ text += "\\%03d" % c
return text
# Unicode label mode. Escape only special characters and values < 0x20
- text = ''
+ text = ""
for uc in label:
if uc in _escaped_text:
- text += '\\' + uc
- elif uc <= '\x20':
- text += '\\%03d' % ord(uc)
+ text += "\\" + uc
+ elif uc <= "\x20":
+ text += "\\%03d" % ord(uc)
else:
text += uc
return text
pass
def is_idna(self, label: bytes) -> bool:
- return label.lower().startswith(b'xn--')
+ return label.lower().startswith(b"xn--")
def encode(self, label: str) -> bytes:
raise NotImplementedError # pragma: no cover
# We do not apply any IDNA policy on decode.
if self.is_idna(label):
try:
- slabel = label[4:].decode('punycode')
+ slabel = label[4:].decode("punycode")
return _escapify(slabel)
except Exception as e:
raise IDNAException(idna_exception=e)
class IDNA2003Codec(IDNACodec):
"""IDNA 2003 encoder/decoder."""
- def __init__(self, strict_decode: bool=False):
+ def __init__(self, strict_decode: bool = False):
"""Initialize the IDNA 2003 encoder/decoder.
*strict_decode* is a ``bool``. If `True`, then IDNA2003 checking
def encode(self, label: str) -> bytes:
"""Encode *label*."""
- if label == '':
- return b''
+ if label == "":
+ return b""
try:
return encodings.idna.ToASCII(label)
except UnicodeError:
"""Decode *label*."""
if not self.strict_decode:
return super().decode(label)
- if label == b'':
- return ''
+ if label == b"":
+ return ""
try:
return _escapify(encodings.idna.ToUnicode(label))
except Exception as e:
class IDNA2008Codec(IDNACodec):
- """IDNA 2008 encoder/decoder.
- """
-
- def __init__(self, uts_46: bool=False, transitional: bool=False,
- allow_pure_ascii: bool=False, strict_decode: bool=False):
+ """IDNA 2008 encoder/decoder."""
+
+ def __init__(
+ self,
+ uts_46: bool = False,
+ transitional: bool = False,
+ allow_pure_ascii: bool = False,
+ strict_decode: bool = False,
+ ):
"""Initialize the IDNA 2008 encoder/decoder.
*uts_46* is a ``bool``. If True, apply Unicode IDNA
self.strict_decode = strict_decode
def encode(self, label: str) -> bytes:
- if label == '':
- return b''
+ if label == "":
+ return b""
if self.allow_pure_ascii and is_all_ascii(label):
- encoded = label.encode('ascii')
+ encoded = label.encode("ascii")
if len(encoded) > 63:
raise LabelTooLong
return encoded
label = idna.uts46_remap(label, False, self.transitional)
return idna.alabel(label)
except idna.IDNAError as e:
- if e.args[0] == 'Label too long':
+ if e.args[0] == "Label too long":
raise LabelTooLong
else:
raise IDNAException(idna_exception=e)
def decode(self, label: bytes) -> str:
if not self.strict_decode:
return super().decode(label)
- if label == b'':
- return ''
+ if label == b"":
+ return ""
if not have_idna_2008:
raise NoIDNA2008
try:
except (idna.IDNAError, UnicodeError) as e:
raise IDNAException(idna_exception=e)
+
IDNA_2003_Practical = IDNA2003Codec(False)
IDNA_2003_Strict = IDNA2003Codec(True)
IDNA_2003 = IDNA_2003_Practical
IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False)
IDNA_2008 = IDNA_2008_Practical
+
def _validate_labels(labels: Tuple[bytes, ...]) -> None:
"""Check for empty labels in the middle of a label sequence,
labels that are too long, and for too many labels.
total += ll + 1
if ll > 63:
raise LabelTooLong
- if i < 0 and label == b'':
+ if i < 0 and label == b"":
i = j
j += 1
if total > 255:
of the class are immutable.
"""
- __slots__ = ['labels']
+ __slots__ = ["labels"]
def __init__(self, labels: Iterable[Union[bytes, str]]):
- """*labels* is any iterable whose values are ``str`` or ``bytes``.
- """
+ """*labels* is any iterable whose values are ``str`` or ``bytes``."""
blabels = [_maybe_convert_to_binary(x) for x in labels]
self.labels = tuple(blabels)
def __getstate__(self):
# Names can be pickled
- return {'labels': self.labels}
+ return {"labels": self.labels}
def __setstate__(self, state):
- super().__setattr__('labels', state['labels'])
+ super().__setattr__("labels", state["labels"])
_validate_labels(self.labels)
def is_absolute(self) -> bool:
Returns a ``bool``.
"""
- return len(self.labels) > 0 and self.labels[-1] == b''
+ return len(self.labels) > 0 and self.labels[-1] == b""
def is_wild(self) -> bool:
"""Is this name wild? (I.e. Is the least significant label '*'?)
Returns a ``bool``.
"""
- return len(self.labels) > 0 and self.labels[0] == b'*'
+ return len(self.labels) > 0 and self.labels[0] == b"*"
def __hash__(self) -> int:
"""Return a case-insensitive hash of the name.
h += (h << 3) + c
return h
- def fullcompare(self, other: 'Name') -> Tuple[NameRelation, int, int]:
+ def fullcompare(self, other: "Name") -> Tuple[NameRelation, int, int]:
"""Compare two names, returning a 3-tuple
``(relation, order, nlabels)``.
namereln = NameRelation.EQUAL
return (namereln, order, nlabels)
- def is_subdomain(self, other: 'Name') -> bool:
+ def is_subdomain(self, other: "Name") -> bool:
"""Is self a subdomain of other?
Note that the notion of subdomain includes equality, e.g.
return True
return False
- def is_superdomain(self, other: 'Name') -> bool:
+ def is_superdomain(self, other: "Name") -> bool:
"""Is self a superdomain of other?
Note that the notion of superdomain includes equality, e.g.
return True
return False
- def canonicalize(self) -> 'Name':
+ def canonicalize(self) -> "Name":
"""Return a name which is equal to the current name, but is in
DNSSEC canonical form.
"""
return NotImplemented
def __repr__(self):
- return '<DNS name ' + self.__str__() + '>'
+ return "<DNS name " + self.__str__() + ">"
def __str__(self):
return self.to_text(False)
- def to_text(self, omit_final_dot: bool=False) -> str:
+ def to_text(self, omit_final_dot: bool = False) -> str:
"""Convert name to DNS text format.
*omit_final_dot* is a ``bool``. If True, don't emit the final
"""
if len(self.labels) == 0:
- return '@'
- if len(self.labels) == 1 and self.labels[0] == b'':
- return '.'
+ return "@"
+ if len(self.labels) == 1 and self.labels[0] == b"":
+ return "."
if omit_final_dot and self.is_absolute():
l = self.labels[:-1]
else:
l = self.labels
- s = '.'.join(map(_escapify, l))
+ s = ".".join(map(_escapify, l))
return s
- def to_unicode(self, omit_final_dot: bool=False, idna_codec: Optional[IDNACodec]=None) -> str:
+ def to_unicode(
+ self, omit_final_dot: bool = False, idna_codec: Optional[IDNACodec] = None
+ ) -> str:
"""Convert name to Unicode text format.
IDN ACE labels are converted to Unicode.
"""
if len(self.labels) == 0:
- return '@'
- if len(self.labels) == 1 and self.labels[0] == b'':
- return '.'
+ return "@"
+ if len(self.labels) == 1 and self.labels[0] == b"":
+ return "."
if omit_final_dot and self.is_absolute():
l = self.labels[:-1]
else:
l = self.labels
if idna_codec is None:
idna_codec = IDNA_2003_Practical
- return '.'.join([idna_codec.decode(x) for x in l])
+ return ".".join([idna_codec.decode(x) for x in l])
- def to_digestable(self, origin: Optional['Name']=None) -> bytes:
+ def to_digestable(self, origin: Optional["Name"] = None) -> bytes:
"""Convert name to a format suitable for digesting in hashes.
The name is canonicalized and converted to uncompressed wire
assert digest is not None
return digest
- def to_wire(self, file: Optional[Any]=None, compress: Optional[CompressType]=None,
- origin: Optional['Name']=None, canonicalize: bool=False) -> Optional[bytes]:
+ def to_wire(
+ self,
+ file: Optional[Any] = None,
+ compress: Optional[CompressType] = None,
+ origin: Optional["Name"] = None,
+ canonicalize: bool = False,
+ ) -> Optional[bytes]:
"""Convert name to wire format, possibly compressing it.
*file* is the file where the name is emitted (typically an
else:
pos = None
if pos is not None:
- value = 0xc000 + pos
- s = struct.pack('!H', value)
+ value = 0xC000 + pos
+ s = struct.pack("!H", value)
file.write(s)
break
else:
if compress is not None and len(n) > 1:
pos = file.tell()
- if pos <= 0x3fff:
+ if pos <= 0x3FFF:
compress[n] = pos
l = len(label)
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
if l > 0:
if canonicalize:
file.write(label.lower())
def __sub__(self, other):
return self.relativize(other)
- def split(self, depth: int) -> Tuple['Name', 'Name']:
+ def split(self, depth: int) -> Tuple["Name", "Name"]:
"""Split a name into a prefix and suffix names at the specified depth.
*depth* is an ``int`` specifying the number of labels in the suffix
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: 'Name') -> 'Name':
+ def concatenate(self, other: "Name") -> "Name":
"""Return a new name which is the concatenation of self and other.
Raises ``dns.name.AbsoluteConcatenation`` if the name is
labels.extend(list(other.labels))
return Name(labels)
- def relativize(self, origin: 'Name') -> 'Name':
+ def relativize(self, origin: "Name") -> "Name":
"""If the name is a subdomain of *origin*, return a new name which is
the name relative to origin. Otherwise return the name.
else:
return self
- def derelativize(self, origin: 'Name') -> 'Name':
+ def derelativize(self, origin: "Name") -> "Name":
"""If the name is a relative name, return a new name which is the
concatenation of the name and origin. Otherwise return the name.
else:
return self
- def choose_relativity(self, origin: Optional['Name']=None, relativize: bool=True) -> 'Name':
+ def choose_relativity(
+ self, origin: Optional["Name"] = None, relativize: bool = True
+ ) -> "Name":
"""Return a name with the relativity desired by the caller.
If *origin* is ``None``, then the name is returned.
else:
return self
- def parent(self) -> 'Name':
+ def parent(self) -> "Name":
"""Return the parent of the name.
For example, the parent of ``www.dnspython.org.`` is ``dnspython.org``.
raise NoParent
return Name(self.labels[1:])
+
#: The root name, '.'
-root = Name([b''])
+root = Name([b""])
#: The empty name.
empty = Name([])
-def from_unicode(text: str, origin: Optional[Name]=root, idna_codec: Optional[IDNACodec]=None) -> Name:
+
+def from_unicode(
+ text: str, origin: Optional[Name] = root, idna_codec: Optional[IDNACodec] = None
+) -> Name:
"""Convert unicode text into a Name object.
Labels are encoded in IDN ACE form according to rules specified by
if not (origin is None or isinstance(origin, Name)):
raise ValueError("origin must be a Name or None")
labels = []
- label = ''
+ label = ""
escaping = False
edigits = 0
total = 0
if idna_codec is None:
idna_codec = IDNA_2003
- if text == '@':
- text = ''
+ if text == "@":
+ text = ""
if text:
- if text in ['.', '\u3002', '\uff0e', '\uff61']:
- return Name([b'']) # no Unicode "u" on this constant!
+ if text in [".", "\u3002", "\uff0e", "\uff61"]:
+ return Name([b""]) # no Unicode "u" on this constant!
for c in text:
if escaping:
if edigits == 0:
if edigits == 3:
escaping = False
label += chr(total)
- elif c in ['.', '\u3002', '\uff0e', '\uff61']:
+ elif c in [".", "\u3002", "\uff0e", "\uff61"]:
if len(label) == 0:
raise EmptyLabel
labels.append(idna_codec.encode(label))
- label = ''
- elif c == '\\':
+ label = ""
+ elif c == "\\":
escaping = True
edigits = 0
total = 0
if len(label) > 0:
labels.append(idna_codec.encode(label))
else:
- labels.append(b'')
+ labels.append(b"")
- if (len(labels) == 0 or labels[-1] != b'') and origin is not None:
+ if (len(labels) == 0 or labels[-1] != b"") and origin is not None:
labels.extend(list(origin.labels))
return Name(labels)
+
def is_all_ascii(text: str) -> bool:
for c in text:
- if ord(c) > 0x7f:
+ if ord(c) > 0x7F:
return False
return True
-def from_text(text: Union[bytes, str], origin: Optional[Name]=root, idna_codec: Optional[IDNACodec]=None) -> Name:
+
+def from_text(
+ text: Union[bytes, str],
+ origin: Optional[Name] = root,
+ idna_codec: Optional[IDNACodec] = None,
+) -> Name:
"""Convert text into a Name object.
*text*, a ``bytes`` or ``str``, is the text to convert into a name.
#
# then it's still "all ASCII" even though the domain name has
# codepoints > 127.
- text = text.encode('ascii')
+ text = text.encode("ascii")
if not isinstance(text, bytes):
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 = b''
+ label = b""
escaping = False
edigits = 0
total = 0
- if text == b'@':
- text = b''
+ if text == b"@":
+ text = b""
if text:
- if text == b'.':
- return Name([b''])
+ if text == b".":
+ return Name([b""])
for c in text:
- byte_ = struct.pack('!B', c)
+ byte_ = struct.pack("!B", c)
if escaping:
if edigits == 0:
if byte_.isdigit():
edigits += 1
if edigits == 3:
escaping = False
- label += struct.pack('!B', total)
- elif byte_ == b'.':
+ label += struct.pack("!B", total)
+ elif byte_ == b".":
if len(label) == 0:
raise EmptyLabel
labels.append(label)
- label = b''
- elif byte_ == b'\\':
+ label = b""
+ elif byte_ == b"\\":
escaping = True
edigits = 0
total = 0
if len(label) > 0:
labels.append(label)
else:
- labels.append(b'')
- if (len(labels) == 0 or labels[-1] != b'') and origin is not 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)
+
# we need 'dns.wire.Parser' quoted as dns.name and dns.wire depend on each other.
-def from_wire_parser(parser: 'dns.wire.Parser') -> Name:
+
+def from_wire_parser(parser: "dns.wire.Parser") -> Name:
"""Convert possibly compressed wire format into a Name.
*parser* is a dns.wire.Parser.
if count < 64:
labels.append(parser.get_bytes(count))
elif count >= 192:
- current = (count & 0x3f) * 256 + parser.get_uint8()
+ current = (count & 0x3F) * 256 + parser.get_uint8()
if current >= biggest_pointer:
raise BadPointer
biggest_pointer = current
else:
raise BadLabelType
count = parser.get_uint8()
- labels.append(b'')
+ labels.append(b"")
return Name(labels)
def __setitem__(self, key, value):
if not isinstance(key, dns.name.Name):
- raise ValueError('NameDict key must be a name')
+ raise ValueError("NameDict key must be a name")
self.__store[key] = value
self.__update_max_depth(key)
# "neutral" types can coexist with a CNAME and thus are not "other data"
_neutral_types = {
- dns.rdatatype.NSEC, # RFC 4035 section 2.5
+ dns.rdatatype.NSEC, # RFC 4035 section 2.5
dns.rdatatype.NSEC3, # This is not likely to happen, but not impossible!
- dns.rdatatype.KEY, # RFC 4035 section 2.5, RFC 3007
+ dns.rdatatype.KEY, # RFC 4035 section 2.5, RFC 3007
}
+
def _matches_type_or_its_signature(rdtypes, rdtype, covers):
- return rdtype in rdtypes or \
- (rdtype == dns.rdatatype.RRSIG and covers in rdtypes)
+ return rdtype in rdtypes or (rdtype == dns.rdatatype.RRSIG and covers in rdtypes)
@enum.unique
class NodeKind(enum.Enum):
- """Rdatasets in nodes
- """
- REGULAR = 0 # a.k.a "other data"
+ """Rdatasets in nodes"""
+
+ REGULAR = 0 # a.k.a "other data"
NEUTRAL = 1
CNAME = 2
@classmethod
- def classify(cls, rdtype: dns.rdatatype.RdataType, covers: dns.rdatatype.RdataType) -> 'NodeKind':
+ def classify(
+ cls, rdtype: dns.rdatatype.RdataType, covers: dns.rdatatype.RdataType
+ ) -> "NodeKind":
if _matches_type_or_its_signature(_cname_types, rdtype, covers):
return NodeKind.CNAME
elif _matches_type_or_its_signature(_neutral_types, rdtype, covers):
return NodeKind.REGULAR
@classmethod
- def classify_rdataset(cls, rdataset: dns.rdataset.Rdataset) -> 'NodeKind':
+ def classify_rdataset(cls, rdataset: dns.rdataset.Rdataset) -> "NodeKind":
return cls.classify(rdataset.rdtype, rdataset.covers)
deleted.
"""
- __slots__ = ['rdatasets']
+ __slots__ = ["rdatasets"]
def __init__(self):
# the set of rdatasets, represented as a list.
for rds in self.rdatasets:
if len(rds) > 0:
s.write(rds.to_text(name, **kw)) # type: ignore[arg-type]
- s.write('\n')
+ s.write("\n")
return s.getvalue()[:-1]
def __repr__(self):
- return '<DNS node ' + str(id(self)) + '>'
+ return "<DNS node " + str(id(self)) + ">"
def __eq__(self, other):
#
if len(self.rdatasets) > 0:
kind = NodeKind.classify_rdataset(rdataset)
if kind == NodeKind.CNAME:
- self.rdatasets = [rds for rds in self.rdatasets if
- NodeKind.classify_rdataset(rds) !=
- NodeKind.REGULAR]
+ self.rdatasets = [
+ rds
+ for rds in self.rdatasets
+ if NodeKind.classify_rdataset(rds) != NodeKind.REGULAR
+ ]
elif kind == NodeKind.REGULAR:
- self.rdatasets = [rds for rds in self.rdatasets if
- NodeKind.classify_rdataset(rds) !=
- NodeKind.CNAME]
+ self.rdatasets = [
+ rds
+ for rds in self.rdatasets
+ if NodeKind.classify_rdataset(rds) != NodeKind.CNAME
+ ]
# Otherwise the rdataset is NodeKind.NEUTRAL and we do not need to
# edit self.rdatasets.
self.rdatasets.append(rdataset)
- def find_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> dns.rdataset.Rdataset:
+ def find_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> dns.rdataset.Rdataset:
"""Find an rdataset matching the specified properties in the
current node.
self._append_rdataset(rds)
return rds
- def get_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> Optional[dns.rdataset.Rdataset]:
"""Get an rdataset matching the specified properties in the
current node.
rds = None
return rds
- def delete_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE) -> None:
+ def delete_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ ) -> None:
"""Delete the rdataset matching the specified properties in the
current node.
"""
if not isinstance(replacement, dns.rdataset.Rdataset):
- raise ValueError('replacement is not an rdataset')
+ raise ValueError("replacement is not an rdataset")
if isinstance(replacement, dns.rrset.RRset):
# RRsets are not good replacements as the match() method
# is not compatible.
replacement = replacement.to_rdataset()
- self.delete_rdataset(replacement.rdclass, replacement.rdtype,
- replacement.covers)
+ self.delete_rdataset(
+ replacement.rdclass, replacement.rdtype, replacement.covers
+ )
self._append_rdataset(replacement)
def classify(self) -> NodeKind:
[dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets]
)
- def find_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> dns.rdataset.Rdataset:
+ def find_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> dns.rdataset.Rdataset:
if create:
raise TypeError("immutable")
return super().find_rdataset(rdclass, rdtype, covers, False)
- def get_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> Optional[dns.rdataset.Rdataset]:
if create:
raise TypeError("immutable")
return super().get_rdataset(rdclass, rdtype, covers, False)
- def delete_rdataset(self,
- rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE) -> None:
+ def delete_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ ) -> None:
raise TypeError("immutable")
def replace_rdataset(self, replacement: dns.rdataset.Rdataset) -> None:
import dns.enum
import dns.exception
+
class Opcode(dns.enum.IntEnum):
#: Query
QUERY = 0
return from_flags(flags) == Opcode.UPDATE
+
### BEGIN generated Opcode constants
QUERY = Opcode.QUERY
import requests
from requests_toolbelt.adapters.source import SourceAddressAdapter
from requests_toolbelt.adapters.host_header_ssl import HostHeaderSSLAdapter
+
_have_requests = True
except ImportError: # pragma: no cover
_have_requests = False
_have_http2 = False
try:
import httpx
+
_have_httpx = True
try:
# See if http2 support is available.
try:
import ssl
except ImportError: # pragma: no cover
- class ssl: # type: ignore
+ class ssl: # type: ignore
class WantReadException(Exception):
pass
@classmethod
def create_default_context(cls, *args, **kwargs):
- raise Exception('no ssl support')
+ raise Exception("no ssl support")
+
# Function used to create a socket. Can be overridden if needed in special
# situations.
socket_factory = socket.socket
+
class UnexpectedSource(dns.exception.DNSException):
"""A DNS query response came from an unexpected address or port."""
_selector_class = selector_class
-if hasattr(selectors, 'PollSelector'):
+
+if hasattr(selectors, "PollSelector"):
# Prefer poll() on platforms that support it because it has no
# limits on the maximum value of a file descriptor (plus it will
# be more efficient for high values).
# sent to destination.
if not destination:
return True
- if _addresses_equal(af, from_address, destination) or \
- (dns.inet.is_multicast(destination[0]) and
- from_address[1:] == destination[1:]):
+ if _addresses_equal(af, from_address, destination) or (
+ dns.inet.is_multicast(destination[0]) and from_address[1:] == destination[1:]
+ ):
return True
elif ignore_unexpected:
return False
- raise UnexpectedSource(f'got a response from {from_address} instead of '
- f'{destination}')
+ raise UnexpectedSource(
+ f"got a response from {from_address} instead of " f"{destination}"
+ )
-def _destination_and_source(where, port, source, source_port,
- where_must_be_address=True):
+def _destination_and_source(
+ where, port, source, source_port, where_must_be_address=True
+):
# Apply defaults and compute destination and source tuples
# suitable for use in connect(), sendto(), or bind().
af = None
if af:
# We know the destination af, so source had better agree!
if saf != af:
- raise ValueError('different address families for source ' +
- 'and destination')
+ raise ValueError(
+ "different address families for source " + "and destination"
+ )
else:
# We didn't know the destination af, but we know the source,
# so that's our af.
# need to return a source, and we need to use the appropriate
# wildcard address as the address.
if af == socket.AF_INET:
- source = '0.0.0.0'
+ source = "0.0.0.0"
elif af == socket.AF_INET6:
- source = '::'
+ source = "::"
else:
- raise ValueError('source_port specified but address family is '
- 'unknown')
+ raise ValueError("source_port specified but address family is " "unknown")
# Convert high-level (address, port) tuples into low-level address
# tuples.
if destination:
source = dns.inet.low_level_address_tuple((source, source_port), af)
return (af, destination, source)
+
def _make_socket(af, type, source, ssl_context=None, server_hostname=None):
s = socket_factory(af, type)
try:
s.bind(source)
if ssl_context:
# LGTM gets a false positive here, as our default context is OK
- return ssl_context.wrap_socket(s, do_handshake_on_connect=False, # lgtm[py/insecure-protocol]
- server_hostname=server_hostname)
+ return ssl_context.wrap_socket(
+ s,
+ do_handshake_on_connect=False, # lgtm[py/insecure-protocol]
+ server_hostname=server_hostname,
+ )
else:
return s
except Exception:
s.close()
raise
-def https(q: dns.message.Message, where: str, timeout: Optional[float]=None,
- port: int=443, source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- session: Optional[Any]=None, path: str='/dns-query', post: bool=True,
- bootstrap_address: Optional[str]=None, verify: bool=True) -> dns.message.Message:
+
+def https(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 443,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ session: Optional[Any] = None,
+ path: str = "/dns-query",
+ post: bool = True,
+ bootstrap_address: Optional[str] = None,
+ verify: bool = True,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via DNS-over-HTTPS.
*q*, a ``dns.message.Message``, the query to send.
"""
if not have_doh:
- raise NoDOH('Neither httpx nor requests is available.') # pragma: no cover
+ raise NoDOH("Neither httpx nor requests is available.") # pragma: no cover
_httpx_ok = _have_httpx
wire = q.to_wire()
- (af, _, source) = _destination_and_source(where, port, source, source_port,
- False)
+ (af, _, source) = _destination_and_source(where, port, source, source_port, False)
transport_adapter = None
transport = None
- headers = {
- "accept": "application/dns-message"
- }
+ headers = {"accept": "application/dns-message"}
if af is not None:
if af == socket.AF_INET:
- url = 'https://{}:{}{}'.format(where, port, path)
+ url = "https://{}:{}{}".format(where, port, path)
elif af == socket.AF_INET6:
- url = 'https://[{}]:{}{}'.format(where, port, path)
+ url = "https://[{}]:{}{}".format(where, port, path)
elif bootstrap_address is not None:
_httpx_ok = False
split_url = urllib.parse.urlsplit(where)
if split_url.hostname is None:
- raise ValueError('DoH URL has no hostname')
- headers['Host'] = split_url.hostname
+ raise ValueError("DoH URL has no hostname")
+ headers["Host"] = split_url.hostname
url = where.replace(split_url.hostname, bootstrap_address)
if _have_requests:
transport_adapter = HostHeaderSSLAdapter()
else:
_is_httpx = False
if _is_httpx and not _httpx_ok:
- raise NoDOH('Session is httpx, but httpx cannot be used for '
- 'the requested operation.')
+ raise NoDOH(
+ "Session is httpx, but httpx cannot be used for "
+ "the requested operation."
+ )
else:
_is_httpx = _httpx_ok
if not _httpx_ok and not _have_requests:
- raise NoDOH('Cannot use httpx for this operation, and '
- 'requests is not available.')
+ raise NoDOH(
+ "Cannot use httpx for this operation, and " "requests is not available."
+ )
with contextlib.ExitStack() as stack:
if not session:
if _is_httpx:
- session = stack.enter_context(httpx.Client(http1=True,
- http2=_have_http2,
- verify=verify,
- transport=transport))
+ session = stack.enter_context(
+ httpx.Client(
+ http1=True,
+ http2=_have_http2,
+ verify=verify,
+ transport=transport,
+ )
+ )
else:
session = stack.enter_context(requests.sessions.Session())
# see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
# GET and POST examples
if post:
- headers.update({
- "content-type": "application/dns-message",
- "content-length": str(len(wire))
- })
+ headers.update(
+ {
+ "content-type": "application/dns-message",
+ "content-length": str(len(wire)),
+ }
+ )
if _is_httpx:
- response = session.post(url, headers=headers, content=wire,
- timeout=timeout)
+ response = session.post(
+ url, headers=headers, content=wire, timeout=timeout
+ )
else:
- response = session.post(url, headers=headers, data=wire,
- timeout=timeout, verify=verify)
+ response = session.post(
+ url, headers=headers, data=wire, timeout=timeout, verify=verify
+ )
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
if _is_httpx:
twire = wire.decode() # httpx does a repr() if we give it bytes
- response = session.get(url, headers=headers,
- timeout=timeout,
- params={"dns": twire})
+ response = session.get(
+ url, headers=headers, timeout=timeout, params={"dns": twire}
+ )
else:
- response = session.get(url, headers=headers,
- timeout=timeout, verify=verify,
- params={"dns": wire})
+ response = session.get(
+ url,
+ headers=headers,
+ timeout=timeout,
+ verify=verify,
+ params={"dns": wire},
+ )
# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
# status codes
if response.status_code < 200 or response.status_code > 299:
- raise ValueError('{} responded with status code {}'
- '\nResponse body: {}'.format(where,
- response.status_code,
- response.content))
- r = dns.message.from_wire(response.content,
- keyring=q.keyring,
- request_mac=q.request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing)
+ raise ValueError(
+ "{} responded with status code {}"
+ "\nResponse body: {}".format(where, response.status_code, response.content)
+ )
+ r = dns.message.from_wire(
+ response.content,
+ keyring=q.keyring,
+ request_mac=q.request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
r.time = response.elapsed.total_seconds()
if not q.is_response(r):
raise BadResponse
return r
+
def _udp_recv(sock, max_size, expiration):
"""Reads a datagram from the socket.
A Timeout exception will be raised if the operation is not completed
_wait_for_writable(sock, expiration)
-def send_udp(sock: Any, what: Union[dns.message.Message, bytes], destination: Any,
- expiration: Optional[float]=None) -> Tuple[int, float]:
+def send_udp(
+ sock: Any,
+ what: Union[dns.message.Message, bytes],
+ destination: Any,
+ expiration: Optional[float] = None,
+) -> Tuple[int, float]:
"""Send a DNS message to the specified UDP socket.
*sock*, a ``socket``.
return (n, sent_time)
-def receive_udp(sock: Any, destination: Optional[Any]=None, expiration: Optional[float]=None,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False,
- keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]]=None, request_mac: Optional[bytes]=b'',
- ignore_trailing: bool=False, raise_on_truncation: bool=False) -> Any:
+def receive_udp(
+ sock: Any,
+ destination: Optional[Any] = None,
+ expiration: Optional[float] = None,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None,
+ request_mac: Optional[bytes] = b"",
+ ignore_trailing: bool = False,
+ raise_on_truncation: bool = False,
+) -> Any:
"""Read a DNS message from a UDP socket.
*sock*, a ``socket``.
the message arrived from.
"""
- wire = b''
+ wire = b""
while True:
(wire, from_address) = _udp_recv(sock, 65535, expiration)
- if _matches_destination(sock.family, from_address, destination,
- ignore_unexpected):
+ if _matches_destination(
+ sock.family, from_address, destination, ignore_unexpected
+ ):
break
received_time = time.time()
- r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing,
- raise_on_truncation=raise_on_truncation)
+ r = dns.message.from_wire(
+ wire,
+ keyring=keyring,
+ request_mac=request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ raise_on_truncation=raise_on_truncation,
+ )
if destination:
return (r, received_time)
else:
return (r, received_time, from_address)
-def udp(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- raise_on_truncation: bool=False, sock: Optional[Any]=None) -> dns.message.Message:
+
+def udp(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ raise_on_truncation: bool = False,
+ sock: Optional[Any] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via UDP.
*q*, a ``dns.message.Message``, the query to send
"""
wire = q.to_wire()
- (af, destination, source) = _destination_and_source(where, port,
- source, source_port)
+ (af, destination, source) = _destination_and_source(
+ where, port, source, source_port
+ )
(begin_time, expiration) = _compute_times(timeout)
with contextlib.ExitStack() as stack:
if sock:
else:
s = stack.enter_context(_make_socket(af, socket.SOCK_DGRAM, source))
send_udp(s, wire, destination, expiration)
- (r, received_time) = receive_udp(s, destination, expiration,
- ignore_unexpected, one_rr_per_rrset,
- q.keyring, q.mac, ignore_trailing,
- raise_on_truncation)
+ (r, received_time) = receive_udp(
+ s,
+ destination,
+ expiration,
+ ignore_unexpected,
+ one_rr_per_rrset,
+ q.keyring,
+ q.mac,
+ ignore_trailing,
+ raise_on_truncation,
+ )
r.time = received_time - begin_time
if not q.is_response(r):
raise BadResponse
return r
- assert False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
-
-def udp_with_fallback(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- ignore_unexpected: bool=False, one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- udp_sock: Optional[Any]=None,
- tcp_sock: Optional[Any]=None) -> Tuple[dns.message.Message, bool]:
+ assert (
+ False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
+ )
+
+
+def udp_with_fallback(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ ignore_unexpected: bool = False,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ udp_sock: Optional[Any] = None,
+ tcp_sock: Optional[Any] = None,
+) -> Tuple[dns.message.Message, bool]:
"""Return the response to the query, trying UDP first and falling back
to TCP if UDP results in a truncated response.
if and only if TCP was used.
"""
try:
- response = udp(q, where, timeout, port, source, source_port,
- ignore_unexpected, one_rr_per_rrset,
- ignore_trailing, True, udp_sock)
+ response = udp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ ignore_unexpected,
+ one_rr_per_rrset,
+ ignore_trailing,
+ True,
+ udp_sock,
+ )
return (response, False)
except dns.message.Truncated:
- response = tcp(q, where, timeout, port, source, source_port,
- one_rr_per_rrset, ignore_trailing, tcp_sock)
+ response = tcp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ tcp_sock,
+ )
return (response, True)
+
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.
A Timeout exception will be raised if the operation is not completed
by the expiration time.
"""
- s = b''
+ s = b""
while count > 0:
try:
n = sock.recv(count)
- if n == b'':
+ if n == b"":
raise EOFError
count -= len(n)
s += n
_wait_for_readable(sock, expiration)
-def send_tcp(sock: Any, what: Union[dns.message.Message, bytes],
- expiration: Optional[float]=None) -> Tuple[int, float]:
+def send_tcp(
+ sock: Any,
+ what: Union[dns.message.Message, bytes],
+ expiration: Optional[float] = None,
+) -> Tuple[int, float]:
"""Send a DNS message to the specified TCP socket.
*sock*, a ``socket``.
_net_write(sock, tcpmsg, expiration)
return (len(tcpmsg), sent_time)
-def receive_tcp(sock: Any, expiration: Optional[float]=None, one_rr_per_rrset: bool=False,
- keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]]=None,
- request_mac: Optional[bytes]=b'',
- ignore_trailing: bool=False) -> Tuple[dns.message.Message, float]:
+
+def receive_tcp(
+ sock: Any,
+ expiration: Optional[float] = None,
+ one_rr_per_rrset: bool = False,
+ keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None,
+ request_mac: Optional[bytes] = b"",
+ ignore_trailing: bool = False,
+) -> Tuple[dns.message.Message, float]:
"""Read a DNS message from a TCP socket.
*sock*, a ``socket``.
(l,) = struct.unpack("!H", ldata)
wire = _net_read(sock, l, expiration)
received_time = time.time()
- r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
- one_rr_per_rrset=one_rr_per_rrset,
- ignore_trailing=ignore_trailing)
+ r = dns.message.from_wire(
+ wire,
+ keyring=keyring,
+ request_mac=request_mac,
+ one_rr_per_rrset=one_rr_per_rrset,
+ ignore_trailing=ignore_trailing,
+ )
return (r, received_time)
+
def _connect(s, address, expiration):
err = s.connect_ex(address)
if err == 0:
raise OSError(err, os.strerror(err))
-def tcp(q: dns.message.Message, where: str, timeout: Optional[float]=None, port: int=53,
- source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False,
- sock: Optional[Any]=None) -> dns.message.Message:
+def tcp(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ sock: Optional[Any] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via TCP.
*q*, a ``dns.message.Message``, the query to send
if sock:
s = sock
else:
- (af, destination, source) = _destination_and_source(where, port,
- source,
- source_port)
- s = stack.enter_context(_make_socket(af, socket.SOCK_STREAM,
- source))
+ (af, destination, source) = _destination_and_source(
+ where, port, source, source_port
+ )
+ s = stack.enter_context(_make_socket(af, socket.SOCK_STREAM, source))
_connect(s, destination, expiration)
send_tcp(s, wire, expiration)
- (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset,
- q.keyring, q.mac, ignore_trailing)
+ (r, received_time) = receive_tcp(
+ s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing
+ )
r.time = received_time - begin_time
if not q.is_response(r):
raise BadResponse
return r
- assert False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
+ assert (
+ False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
+ )
def _tls_handshake(s, expiration):
_wait_for_writable(s, expiration)
-def tls(q: dns.message.Message, where: str, timeout: Optional[float]=None,
- port: int=853, source: Optional[str]=None, source_port: int=0,
- one_rr_per_rrset: bool=False, ignore_trailing: bool=False, sock: Optional[ssl.SSLSocket]=None,
- ssl_context: Optional[ssl.SSLContext]=None,
- server_hostname: Optional[str]=None) -> dns.message.Message:
+def tls(
+ q: dns.message.Message,
+ where: str,
+ timeout: Optional[float] = None,
+ port: int = 853,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ one_rr_per_rrset: bool = False,
+ ignore_trailing: bool = False,
+ sock: Optional[ssl.SSLSocket] = None,
+ ssl_context: Optional[ssl.SSLContext] = None,
+ server_hostname: Optional[str] = None,
+) -> dns.message.Message:
"""Return the response obtained after sending a query via TLS.
*q*, a ``dns.message.Message``, the query to send
#
# If a socket was provided, there's no special TLS handling needed.
#
- return tcp(q, where, timeout, port, source, source_port,
- one_rr_per_rrset, ignore_trailing, sock)
+ return tcp(
+ q,
+ where,
+ timeout,
+ port,
+ source,
+ source_port,
+ one_rr_per_rrset,
+ ignore_trailing,
+ sock,
+ )
wire = q.to_wire()
(begin_time, expiration) = _compute_times(timeout)
- (af, destination, source) = _destination_and_source(where, port,
- source, source_port)
+ (af, destination, source) = _destination_and_source(
+ where, port, source, source_port
+ )
if ssl_context is None and not sock:
# LGTM complains about this because the default might permit TLS < 1.2
# for compatibility, but the python documentation says that explicit
if server_hostname is None:
ssl_context.check_hostname = False
- with _make_socket(af, socket.SOCK_STREAM, source, ssl_context=ssl_context,
- server_hostname=server_hostname) as s:
+ with _make_socket(
+ af,
+ socket.SOCK_STREAM,
+ source,
+ ssl_context=ssl_context,
+ server_hostname=server_hostname,
+ ) as s:
_connect(s, destination, expiration)
_tls_handshake(s, expiration)
send_tcp(s, wire, expiration)
- (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset,
- q.keyring, q.mac, ignore_trailing)
+ (r, received_time) = receive_tcp(
+ s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing
+ )
r.time = received_time - begin_time
if not q.is_response(r):
raise BadResponse
return r
- assert False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
-
-def xfr(where: str, zone: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.AXFR,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- timeout: Optional[float]=None, port: int=53,
- keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]]=None,
- keyname: Optional[Union[dns.name.Name, str]]=None, relativize: bool=True,
- lifetime: Optional[float]=None, source: Optional[str]=None, source_port: int=0,
- serial: int=0, use_udp: bool=False,
- keyalgorithm: Union[dns.name.Name, str]=dns.tsig.default_algorithm) -> Any:
+ assert (
+ False # help mypy figure out we can't get here lgtm[py/unreachable-statement]
+ )
+
+
+def xfr(
+ where: str,
+ zone: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.AXFR,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ timeout: Optional[float] = None,
+ port: int = 53,
+ keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None,
+ keyname: Optional[Union[dns.name.Name, str]] = None,
+ relativize: bool = True,
+ lifetime: Optional[float] = None,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ serial: int = 0,
+ use_udp: bool = False,
+ keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm,
+) -> Any:
"""Return a generator for the responses to a zone transfer.
*where*, a ``str`` containing an IPv4 or IPv6 address, where
rdtype = dns.rdatatype.RdataType.make(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)
+ rrset = dns.rrset.from_text(zone, 0, "IN", "SOA", ". . %u 0 0 0 0" % serial)
q.authority.append(rrset)
if keyring is not None:
q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
wire = q.to_wire()
- (af, destination, source) = _destination_and_source(where, port,
- source, source_port)
+ (af, destination, source) = _destination_and_source(
+ where, port, source, source_port
+ )
if use_udp and rdtype != dns.rdatatype.IXFR:
- raise ValueError('cannot do a UDP AXFR')
+ raise ValueError("cannot do a UDP AXFR")
sock_type = socket.SOCK_DGRAM if use_udp else socket.SOCK_STREAM
with _make_socket(af, sock_type, source) as s:
(_, expiration) = _compute_times(lifetime)
tsig_ctx = None
while not done:
(_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or \
- (expiration is not None and mexpiration > expiration):
+ if mexpiration is None or (
+ expiration is not None and mexpiration > expiration
+ ):
mexpiration = expiration
if use_udp:
(wire, _) = _udp_recv(s, 65535, mexpiration)
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, one_rr_per_rrset=is_ixfr)
+ 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,
+ one_rr_per_rrset=is_ixfr,
+ )
rcode = r.rcode()
if rcode != dns.rcode.NOERROR:
raise TransferError(rcode)
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")
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
# finished. If this is an IXFR we also check that we're
# seeing 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)):
+ if rrset == soa_rrset and (
+ rdtype == dns.rdatatype.AXFR
+ or (rdtype == dns.rdatatype.IXFR and delete_mode)
+ ):
done = True
elif expecting_SOA:
#
TRY_FIRST means "try to use UDP but fall back to TCP if needed"
ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed"
"""
+
NEVER = 0
TRY_FIRST = 1
ONLY = 2
-def inbound_xfr(where: str, txn_manager: dns.transaction.TransactionManager,
- query: Optional[dns.message.Message]=None,
- port: int=53, timeout: Optional[float]=None, lifetime: Optional[float]=None,
- source: Optional[str]=None, source_port: int=0, udp_mode: UDPMode=UDPMode.NEVER) -> None:
+def inbound_xfr(
+ where: str,
+ txn_manager: dns.transaction.TransactionManager,
+ query: Optional[dns.message.Message] = None,
+ port: int = 53,
+ timeout: Optional[float] = None,
+ lifetime: Optional[float] = None,
+ source: Optional[str] = None,
+ source_port: int = 0,
+ udp_mode: UDPMode = UDPMode.NEVER,
+) -> None:
"""Conduct an inbound transfer and apply it via a transaction from the
txn_manager.
is_ixfr = rdtype == dns.rdatatype.IXFR
origin = txn_manager.from_wire_origin()
wire = query.to_wire()
- (af, destination, source) = _destination_and_source(where, port,
- source, source_port)
+ (af, destination, source) = _destination_and_source(
+ where, port, source, source_port
+ )
(_, expiration) = _compute_times(lifetime)
retry = True
while retry:
else:
tcpmsg = struct.pack("!H", len(wire)) + wire
_net_write(s, tcpmsg, expiration)
- with dns.xfr.Inbound(txn_manager, rdtype, serial,
- is_udp) as inbound:
+ with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound:
done = False
tsig_ctx = None
while not done:
(_, mexpiration) = _compute_times(timeout)
- if mexpiration is None or \
- (expiration is not None and mexpiration > expiration):
+ if mexpiration is None or (
+ expiration is not None and mexpiration > expiration
+ ):
mexpiration = expiration
if is_udp:
(rwire, _) = _udp_recv(s, 65535, mexpiration)
ldata = _net_read(s, 2, mexpiration)
(l,) = struct.unpack("!H", ldata)
rwire = _net_read(s, l, mexpiration)
- r = dns.message.from_wire(rwire, keyring=query.keyring,
- request_mac=query.mac, xfr=True,
- origin=origin, tsig_ctx=tsig_ctx,
- multi=(not is_udp),
- one_rr_per_rrset=is_ixfr)
+ r = dns.message.from_wire(
+ rwire,
+ keyring=query.keyring,
+ request_mac=query.mac,
+ xfr=True,
+ origin=origin,
+ tsig_ctx=tsig_ctx,
+ multi=(not is_udp),
+ one_rr_per_rrset=is_ixfr,
+ )
try:
done = inbound.process_message(r)
except dns.xfr.UseTCP:
import dns.enum
import dns.exception
+
class Rcode(dns.enum.IntEnum):
#: No error
NOERROR = 0
Returns a ``dns.rcode.Rcode``.
"""
- value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
+ value = (flags & 0x000F) | ((ednsflags >> 20) & 0xFF0)
return Rcode.make(value)
"""
if value < 0 or value > 4095:
- raise ValueError('rcode must be >= 0 and <= 4095')
- v = value & 0xf
- ev = (value & 0xff0) << 20
+ raise ValueError("rcode must be >= 0 and <= 4095")
+ v = value & 0xF
+ ev = (value & 0xFF0) << 20
return (v, ev)
-def to_text(value: Rcode, tsig: bool=False) -> str:
+def to_text(value: Rcode, tsig: bool = False) -> str:
"""Convert rcode into text.
*value*, a ``dns.rcode.Rcode``, the rcode.
"""
if tsig and value == Rcode.BADVERS:
- return 'BADSIG'
+ return "BADSIG"
return Rcode.to_text(value)
+
### BEGIN generated Rcode constants
NOERROR = Rcode.NOERROR
"""
-def _wordbreak(data, chunksize=_chunksize, separator=b' '):
+def _wordbreak(data, chunksize=_chunksize, separator=b" "):
"""Break a binary string into chunks of chunksize characters separated by
a space.
"""
if not chunksize:
return data.decode()
- return separator.join([data[i:i + chunksize]
- for i
- in range(0, len(data), chunksize)]).decode()
+ return separator.join(
+ [data[i : i + chunksize] for i in range(0, len(data), chunksize)]
+ ).decode()
# pylint: disable=unused-argument
-def _hexify(data, chunksize=_chunksize, separator=b' ', **kw):
+
+def _hexify(data, chunksize=_chunksize, separator=b" ", **kw):
"""Convert a binary string into its hex encoding, broken up into chunks
of chunksize characters separated by a separator.
"""
return _wordbreak(binascii.hexlify(data), chunksize, separator)
-def _base64ify(data, chunksize=_chunksize, separator=b' ', **kw):
+def _base64ify(data, chunksize=_chunksize, separator=b" ", **kw):
"""Convert a binary string into its base64 encoding, broken up into chunks
of chunksize characters separated by a separator.
"""
return _wordbreak(base64.b64encode(data), chunksize, separator)
+
# pylint: enable=unused-argument
__escaped = b'"\\'
+
def _escapify(qstring):
"""Escape the characters in a quoted string which need it."""
if not isinstance(qstring, bytearray):
qstring = bytearray(qstring)
- text = ''
+ text = ""
for c in qstring:
if c in __escaped:
- text += '\\' + chr(c)
+ text += "\\" + chr(c)
elif c >= 0x20 and c < 0x7F:
text += chr(c)
else:
- text += '\\%03d' % c
+ text += "\\%03d" % c
return text
for i in range(len(what) - 1, -1, -1):
if what[i] != 0:
- return what[0: i + 1]
+ return what[0 : i + 1]
return what[0:1]
+
# So we don't have to edit all the rdata classes...
_constify = dns.immutable.constify
class Rdata:
"""Base class for all DNS rdata types."""
- __slots__ = ['rdclass', 'rdtype', 'rdcomment']
+ __slots__ = ["rdclass", "rdtype", "rdcomment"]
def __init__(self, rdclass, rdtype):
"""Initialize an rdata.
self.rdcomment: Optional[str] = None
def _get_all_slots(self):
- return itertools.chain.from_iterable(getattr(cls, '__slots__', [])
- for cls in self.__class__.__mro__)
+ return itertools.chain.from_iterable(
+ getattr(cls, "__slots__", []) for cls in self.__class__.__mro__
+ )
def __getstate__(self):
# We used to try to do a tuple of all slots here, but it
def __setstate__(self, state):
for slot, val in state.items():
object.__setattr__(self, slot, val)
- if not hasattr(self, 'rdcomment'):
+ if not hasattr(self, "rdcomment"):
# Pickled rdata from 2.0.x might not have a rdcomment, so add
# it if needed.
- object.__setattr__(self, 'rdcomment', None)
+ object.__setattr__(self, "rdcomment", None)
def covers(self) -> dns.rdatatype.RdataType:
"""Return the type a Rdata covers.
return self.covers() << 16 | self.rdtype
- def to_text(self, origin: Optional[dns.name.Name]=None, relativize: bool=True, **kw: Dict[str, Any]) -> str:
+ def to_text(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ **kw: Dict[str, Any]
+ ) -> str:
"""Convert an rdata to text format.
Returns a ``str``.
raise NotImplementedError # pragma: no cover
- def _to_wire(self, file: Optional[Any], compress: Optional[dns.name.CompressType]=None,
- origin: Optional[dns.name.Name]=None, canonicalize: bool=False) -> bytes:
+ def _to_wire(
+ self,
+ file: Optional[Any],
+ compress: Optional[dns.name.CompressType] = None,
+ origin: Optional[dns.name.Name] = None,
+ canonicalize: bool = False,
+ ) -> bytes:
raise NotImplementedError # pragma: no cover
- def to_wire(self, file: Optional[Any]=None, compress: Optional[dns.name.CompressType]=None,
- origin: Optional[dns.name.Name]=None, canonicalize: bool=False) -> bytes:
+ def to_wire(
+ self,
+ file: Optional[Any] = None,
+ compress: Optional[dns.name.CompressType] = None,
+ origin: Optional[dns.name.Name] = None,
+ canonicalize: bool = False,
+ ) -> bytes:
"""Convert an rdata to wire format.
Returns a ``bytes`` or ``None``.
self._to_wire(f, compress, origin, canonicalize)
return f.getvalue()
- def to_generic(self, origin: Optional[dns.name.Name]=None) -> 'dns.rdata.GenericRdata':
+ def to_generic(
+ self, origin: Optional[dns.name.Name] = None
+ ) -> "dns.rdata.GenericRdata":
"""Creates a dns.rdata.GenericRdata equivalent of this rdata.
Returns a ``dns.rdata.GenericRdata``.
"""
- return dns.rdata.GenericRdata(self.rdclass, self.rdtype,
- self.to_wire(origin=origin))
+ return dns.rdata.GenericRdata(
+ self.rdclass, self.rdtype, self.to_wire(origin=origin)
+ )
- def to_digestable(self, origin: Optional[dns.name.Name]=None) -> bytes:
+ def to_digestable(self, origin: Optional[dns.name.Name] = None) -> bytes:
"""Convert rdata to a format suitable for digesting in hashes. This
is also the DNSSEC canonical form.
def __repr__(self):
covers = self.covers()
if covers == dns.rdatatype.NONE:
- ctext = ''
+ ctext = ""
else:
- ctext = '(' + dns.rdatatype.to_text(covers) + ')'
- return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
- dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + \
- str(self) + '>'
+ ctext = "(" + dns.rdatatype.to_text(covers) + ")"
+ return (
+ "<DNS "
+ + dns.rdataclass.to_text(self.rdclass)
+ + " "
+ + dns.rdatatype.to_text(self.rdtype)
+ + ctext
+ + " rdata: "
+ + str(self)
+ + ">"
+ )
def __str__(self):
return self.to_text()
return not self.__eq__(other)
def __lt__(self, other):
- if not isinstance(other, Rdata) or \
- self.rdclass != other.rdclass or self.rdtype != other.rdtype:
+ if (
+ not isinstance(other, Rdata)
+ or 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:
+ if (
+ not isinstance(other, Rdata)
+ or 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:
+ if (
+ not isinstance(other, Rdata)
+ or 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:
+ if (
+ not isinstance(other, Rdata)
+ or self.rdclass != other.rdclass
+ or self.rdtype != other.rdtype
+ ):
return NotImplemented
return self._cmp(other) > 0
return hash(self.to_digestable(dns.name.root))
@classmethod
- def from_text(cls, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- tok: dns.tokenizer.Tokenizer, origin: Optional[dns.name.Name]=None, relativize: bool=True,
- relativize_to: Optional[dns.name.Name]=None) -> 'Rdata':
+ def from_text(
+ cls,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ tok: dns.tokenizer.Tokenizer,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+ ) -> "Rdata":
raise NotImplementedError # pragma: no cover
@classmethod
- def from_wire_parser(cls, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- parser: dns.wire.Parser, origin: Optional[dns.name.Name]=None) -> 'Rdata':
+ def from_wire_parser(
+ cls,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ parser: dns.wire.Parser,
+ origin: Optional[dns.name.Name] = None,
+ ) -> "Rdata":
raise NotImplementedError # pragma: no cover
- def replace(self, **kwargs: Dict[str, Any]) -> 'Rdata':
+ def replace(self, **kwargs: Dict[str, Any]) -> "Rdata":
"""
Create a new Rdata instance based on the instance replace was
invoked on. It is possible to pass different parameters to
# Ensure that all of the arguments correspond to valid fields.
# Don't allow rdclass or rdtype to be changed, though.
for key in kwargs:
- if key == 'rdcomment':
+ if key == "rdcomment":
continue
if key not in parameters:
- raise AttributeError("'{}' object has no attribute '{}'"
- .format(self.__class__.__name__, key))
- if key in ('rdclass', 'rdtype'):
- raise AttributeError("Cannot overwrite '{}' attribute '{}'"
- .format(self.__class__.__name__, key))
+ raise AttributeError(
+ "'{}' object has no attribute '{}'".format(
+ self.__class__.__name__, key
+ )
+ )
+ if key in ("rdclass", "rdtype"):
+ raise AttributeError(
+ "Cannot overwrite '{}' attribute '{}'".format(
+ self.__class__.__name__, key
+ )
+ )
# Construct the parameter list. For each field, use the value in
# kwargs if present, and the current value otherwise.
rd = self.__class__(*args)
# The comment is not set in the constructor, so give it special
# handling.
- rdcomment = kwargs.get('rdcomment', self.rdcomment)
+ rdcomment = kwargs.get("rdcomment", self.rdcomment)
if rdcomment is not None:
- object.__setattr__(rd, 'rdcomment', rdcomment)
+ object.__setattr__(rd, "rdcomment", rdcomment)
return rd
# Type checking and conversion helpers. These are class methods as
return dns.rdatatype.RdataType.make(value)
@classmethod
- def _as_bytes(cls, value: Any, encode: bool=False, max_length: Optional[int]=None,
- empty_ok: bool=True) -> bytes:
+ def _as_bytes(
+ cls,
+ value: Any,
+ encode: bool = False,
+ max_length: Optional[int] = None,
+ empty_ok: bool = True,
+ ) -> bytes:
if encode and isinstance(value, str):
bvalue = value.encode()
elif isinstance(value, bytearray):
elif isinstance(value, bytes):
bvalue = value
else:
- raise ValueError('not bytes')
+ raise ValueError("not bytes")
if max_length is not None and len(bvalue) > max_length:
- raise ValueError('too long')
+ raise ValueError("too long")
if not empty_ok and len(bvalue) == 0:
- raise ValueError('empty bytes not allowed')
+ raise ValueError("empty bytes not allowed")
return bvalue
@classmethod
if isinstance(value, str):
return dns.name.from_text(value)
elif not isinstance(value, dns.name.Name):
- raise ValueError('not a name')
+ raise ValueError("not a name")
return value
@classmethod
def _as_uint8(cls, value):
if not isinstance(value, int):
- raise ValueError('not an integer')
+ raise ValueError("not an integer")
if value < 0 or value > 255:
- raise ValueError('not a uint8')
+ raise ValueError("not a uint8")
return value
@classmethod
def _as_uint16(cls, value):
if not isinstance(value, int):
- raise ValueError('not an integer')
+ raise ValueError("not an integer")
if value < 0 or value > 65535:
- raise ValueError('not a uint16')
+ raise ValueError("not a uint16")
return value
@classmethod
def _as_uint32(cls, value):
if not isinstance(value, int):
- raise ValueError('not an integer')
+ raise ValueError("not an integer")
if value < 0 or value > 4294967295:
- raise ValueError('not a uint32')
+ raise ValueError("not a uint32")
return value
@classmethod
def _as_uint48(cls, value):
if not isinstance(value, int):
- raise ValueError('not an integer')
+ raise ValueError("not an integer")
if value < 0 or value > 281474976710655:
- raise ValueError('not a uint48')
+ raise ValueError("not a uint48")
return value
@classmethod
def _as_int(cls, value, low=None, high=None):
if not isinstance(value, int):
- raise ValueError('not an integer')
+ raise ValueError("not an integer")
if low is not None and value < low:
- raise ValueError('value too small')
+ raise ValueError("value too small")
if high is not None and value > high:
- raise ValueError('value too large')
+ raise ValueError("value too large")
return value
@classmethod
elif isinstance(value, bytes):
return dns.ipv4.inet_ntoa(value)
else:
- raise ValueError('not an IPv4 address')
+ raise ValueError("not an IPv4 address")
@classmethod
def _as_ipv6_address(cls, value):
elif isinstance(value, bytes):
return dns.ipv6.inet_ntoa(value)
else:
- raise ValueError('not an IPv6 address')
+ raise ValueError("not an IPv6 address")
@classmethod
def _as_bool(cls, value):
if isinstance(value, bool):
return value
else:
- raise ValueError('not a boolean')
+ raise ValueError("not a boolean")
@classmethod
def _as_ttl(cls, value):
elif isinstance(value, str):
return dns.ttl.from_text(value)
else:
- raise ValueError('not a TTL')
+ raise ValueError("not a TTL")
@classmethod
def _as_tuple(cls, value, as_value):
random.shuffle(items)
return items
+
@dns.immutable.immutable
class GenericRdata(Rdata):
implementation. It implements the DNS "unknown RRs" scheme.
"""
- __slots__ = ['data']
+ __slots__ = ["data"]
def __init__(self, rdclass, rdtype, data):
super().__init__(rdclass, rdtype)
self.data = data
- def to_text(self, origin: Optional[dns.name.Name]=None, relativize: bool=True, **kw: Dict[str, Any]) -> str:
- return r'\# %d ' % len(self.data) + _hexify(self.data, **kw)
+ def to_text(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ **kw: Dict[str, Any]
+ ) -> str:
+ return r"\# %d " % len(self.data) + _hexify(self.data, **kw)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
token = tok.get()
- if not token.is_identifier() or token.value != r'\#':
- raise dns.exception.SyntaxError(
- r'generic rdata does not start with \#')
+ if not token.is_identifier() or token.value != r"\#":
+ raise dns.exception.SyntaxError(r"generic rdata does not start with \#")
length = tok.get_int()
hex = tok.concatenate_remaining_identifiers(True).encode()
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)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
return cls(rdclass, rdtype, parser.get_remaining())
-_rdata_classes: Dict[Tuple[dns.rdataclass.RdataClass, dns.rdatatype.RdataType], Any] = {}
-_module_prefix = 'dns.rdtypes'
+
+_rdata_classes: Dict[
+ Tuple[dns.rdataclass.RdataClass, dns.rdatatype.RdataType], Any
+] = {}
+_module_prefix = "dns.rdtypes"
+
def get_rdata_class(rdclass, rdtype):
cls = _rdata_classes.get((rdclass, rdtype))
if not cls:
rdclass_text = dns.rdataclass.to_text(rdclass)
rdtype_text = dns.rdatatype.to_text(rdtype)
- rdtype_text = rdtype_text.replace('-', '_')
+ rdtype_text = rdtype_text.replace("-", "_")
try:
- mod = import_module('.'.join([_module_prefix,
- rdclass_text, rdtype_text]))
+ mod = import_module(
+ ".".join([_module_prefix, rdclass_text, rdtype_text])
+ )
cls = getattr(mod, rdtype_text)
_rdata_classes[(rdclass, rdtype)] = cls
except ImportError:
try:
- mod = import_module('.'.join([_module_prefix,
- 'ANY', rdtype_text]))
+ mod = import_module(".".join([_module_prefix, "ANY", rdtype_text]))
cls = getattr(mod, rdtype_text)
_rdata_classes[(dns.rdataclass.ANY, rdtype)] = cls
_rdata_classes[(rdclass, rdtype)] = cls
return cls
-def from_text(rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- tok: Union[dns.tokenizer.Tokenizer, str],
- origin: Optional[dns.name.Name]=None,
- relativize: bool=True, relativize_to: Optional[dns.name.Name]=None,
- idna_codec: Optional[dns.name.IDNACodec]=None) -> Rdata:
+def from_text(
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ tok: Union[dns.tokenizer.Tokenizer, str],
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+) -> Rdata:
"""Build an rdata object from text format.
This function attempts to dynamically load a class which
# peek at first token
token = tok.get()
tok.unget(token)
- if token.is_identifier() and \
- token.value == r'\#':
+ if token.is_identifier() and token.value == r"\#":
#
# Known type using the generic syntax. Extract the
# wire form from the generic syntax, and then run
# from_wire on it.
#
- grdata = GenericRdata.from_text(rdclass, rdtype, tok, origin,
- relativize, relativize_to)
- rdata = from_wire(rdclass, rdtype, grdata.data, 0,
- len(grdata.data), origin)
+ grdata = GenericRdata.from_text(
+ rdclass, rdtype, tok, origin, relativize, relativize_to
+ )
+ rdata = from_wire(
+ rdclass, rdtype, grdata.data, 0, len(grdata.data), origin
+ )
#
# If this comparison isn't equal, then there must have been
# compressed names in the wire format, which is an error,
#
rwire = rdata.to_wire()
if rwire != grdata.data:
- raise dns.exception.SyntaxError('compressed data in '
- 'generic syntax form '
- 'of known rdatatype')
+ raise dns.exception.SyntaxError(
+ "compressed data in "
+ "generic syntax form "
+ "of known rdatatype"
+ )
if rdata is None:
- rdata = cls.from_text(rdclass, rdtype, tok, origin, relativize,
- relativize_to)
+ rdata = cls.from_text(
+ rdclass, rdtype, tok, origin, relativize, relativize_to
+ )
token = tok.get_eol_as_token()
if token.comment is not None:
- object.__setattr__(rdata, 'rdcomment', token.comment)
+ object.__setattr__(rdata, "rdcomment", token.comment)
return rdata
-def from_wire_parser(rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- parser: dns.wire.Parser, origin: Optional[dns.name.Name]=None) -> Rdata:
+def from_wire_parser(
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ parser: dns.wire.Parser,
+ origin: Optional[dns.name.Name] = None,
+) -> Rdata:
"""Build an rdata object from wire format
This function attempts to dynamically load a class which
return cls.from_wire_parser(rdclass, rdtype, parser, origin)
-def from_wire(rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- wire: bytes, current: int, rdlen: int,
- origin: Optional[dns.name.Name]=None) -> Rdata:
+def from_wire(
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ wire: bytes,
+ current: int,
+ rdlen: int,
+ origin: Optional[dns.name.Name] = None,
+) -> Rdata:
"""Build an rdata object from wire format
This function attempts to dynamically load a class which
class RdatatypeExists(dns.exception.DNSException):
"""DNS rdatatype already exists."""
- supp_kwargs = {'rdclass', 'rdtype'}
- fmt = "The rdata type with class {rdclass:d} and rdtype {rdtype:d} " + \
- "already exists."
+
+ supp_kwargs = {"rdclass", "rdtype"}
+ fmt = (
+ "The rdata type with class {rdclass:d} and rdtype {rdtype:d} "
+ + "already exists."
+ )
-def register_type(implementation: Any, rdtype: int, rdtype_text: str, is_singleton: bool=False,
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN) -> None:
+def register_type(
+ implementation: Any,
+ rdtype: int,
+ rdtype_text: str,
+ is_singleton: bool = False,
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+) -> None:
"""Dynamically register a module to handle an rdatatype.
*implementation*, a module implementing the type in the usual dnspython
raise RdatatypeExists(rdclass=rdclass, rdtype=the_rdtype)
except ValueError:
pass
- _rdata_classes[(rdclass, the_rdtype)] = getattr(implementation,
- rdtype_text.replace('-', '_'))
+ _rdata_classes[(rdclass, the_rdtype)] = getattr(
+ implementation, rdtype_text.replace("-", "_")
+ )
dns.rdatatype.register_type(the_rdtype, rdtype_text, is_singleton)
import dns.enum
import dns.exception
+
class RdataClass(dns.enum.IntEnum):
"""DNS Rdata Class"""
+
RESERVED0 = 0
IN = 1
INTERNET = IN
return True
return False
+
### BEGIN generated RdataClass constants
RESERVED0 = RdataClass.RESERVED0
"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)"""
-from typing import Any, cast, Collection, Dict, Iterable, List, Optional, Union
+from typing import Any, cast, Collection, Dict, List, Optional, Union
import io
import random
"""A DNS rdataset."""
- __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl']
+ __slots__ = ["rdclass", "rdtype", "covers", "ttl"]
- def __init__(self, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE, ttl: int=0):
+ def __init__(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ ttl: int = 0,
+ ):
"""Create a new rdataset of the specified class and type.
*rdclass*, a ``dns.rdataclass.RdataClass``, the rdataclass.
elif ttl < self.ttl:
self.ttl = ttl
- def add(self, rd: dns.rdata.Rdata, ttl: Optional[int]=None) -> None: # pylint: disable=arguments-differ
+ def add(
+ self, rd: dns.rdata.Rdata, ttl: Optional[int] = None
+ ) -> None: # pylint: disable=arguments-differ
"""Add the specified rdata to the rdataset.
If the optional *ttl* parameter is supplied, then
raise IncompatibleTypes
if ttl is not None:
self.update_ttl(ttl)
- if self.rdtype == dns.rdatatype.RRSIG or \
- self.rdtype == dns.rdatatype.SIG:
+ if self.rdtype == dns.rdatatype.RRSIG or self.rdtype == dns.rdatatype.SIG:
covers = rd.covers()
if len(self) == 0 and self.covers == dns.rdatatype.NONE:
self.covers = covers
def _rdata_repr(self):
def maybe_truncate(s):
if len(s) > 100:
- return s[:100] + '...'
+ return s[:100] + "..."
return s
- return '[%s]' % ', '.join('<%s>' % maybe_truncate(str(rr))
- for rr in self)
+
+ return "[%s]" % ", ".join("<%s>" % maybe_truncate(str(rr)) for rr in self)
def __repr__(self):
if self.covers == 0:
- ctext = ''
+ ctext = ""
else:
- ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
- return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
- dns.rdatatype.to_text(self.rdtype) + ctext + \
- ' rdataset: ' + self._rdata_repr() + '>'
+ ctext = "(" + dns.rdatatype.to_text(self.covers) + ")"
+ return (
+ "<DNS "
+ + dns.rdataclass.to_text(self.rdclass)
+ + " "
+ + dns.rdatatype.to_text(self.rdtype)
+ + ctext
+ + " rdataset: "
+ + self._rdata_repr()
+ + ">"
+ )
def __str__(self):
return self.to_text()
def __eq__(self, other):
if not isinstance(other, Rdataset):
return False
- if self.rdclass != other.rdclass or \
- self.rdtype != other.rdtype or \
- self.covers != other.covers:
+ if (
+ self.rdclass != other.rdclass
+ or self.rdtype != other.rdtype
+ or self.covers != other.covers
+ ):
return False
return super().__eq__(other)
def __ne__(self, other):
return not self.__eq__(other)
- def to_text(self, name: Optional[dns.name.Name]=None,
- origin: Optional[dns.name.Name]=None,
- relativize: bool=True,
- override_rdclass: Optional[dns.rdataclass.RdataClass]=None,
- want_comments: bool=False, **kw: Dict[str, Any]) -> str:
+ def to_text(
+ self,
+ name: Optional[dns.name.Name] = None,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ override_rdclass: Optional[dns.rdataclass.RdataClass] = None,
+ want_comments: bool = False,
+ **kw: Dict[str, Any],
+ ) -> str:
"""Convert the rdataset into DNS zone file format.
See ``dns.name.Name.choose_relativity`` for more information
if name is not None:
name = name.choose_relativity(origin, relativize)
ntext = str(name)
- pad = ' '
+ pad = " "
else:
- ntext = ''
- pad = ''
+ ntext = ""
+ pad = ""
s = io.StringIO()
if override_rdclass is not None:
rdclass = override_rdclass
# some dynamic updates, so we don't need to print out the TTL
# (which is meaningless anyway).
#
- s.write('{}{}{} {}\n'.format(ntext, pad,
- dns.rdataclass.to_text(rdclass),
- dns.rdatatype.to_text(self.rdtype)))
+ s.write(
+ "{}{}{} {}\n".format(
+ ntext,
+ pad,
+ dns.rdataclass.to_text(rdclass),
+ dns.rdatatype.to_text(self.rdtype),
+ )
+ )
else:
for rd in self:
- extra = ''
+ extra = ""
if want_comments:
if rd.rdcomment:
- extra = f' ;{rd.rdcomment}'
- s.write('%s%s%d %s %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),
- extra))
+ extra = f" ;{rd.rdcomment}"
+ s.write(
+ "%s%s%d %s %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),
+ extra,
+ )
+ )
#
# We strip off the final \n for the caller's convenience in printing
#
return s.getvalue()[:-1]
- def to_wire(self, name: dns.name.Name, file: Any,
- compress: Optional[dns.name.CompressType]=None,
- origin: Optional[dns.name.Name]=None,
- override_rdclass: Optional[dns.rdataclass.RdataClass]=None,
- want_shuffle: bool=True) -> int:
+ def to_wire(
+ self,
+ name: dns.name.Name,
+ file: Any,
+ compress: Optional[dns.name.CompressType] = None,
+ origin: Optional[dns.name.Name] = None,
+ override_rdclass: Optional[dns.rdataclass.RdataClass] = None,
+ want_shuffle: bool = True,
+ ) -> int:
"""Convert the rdataset to wire format.
*name*, a ``dns.name.Name`` is the owner name to use.
l = self
for rd in l:
name.to_wire(file, compress, origin)
- stuff = struct.pack("!HHIH", self.rdtype, rdclass,
- self.ttl, 0)
+ stuff = struct.pack("!HHIH", self.rdtype, rdclass, self.ttl, 0)
file.write(stuff)
start = file.tell()
rd.to_wire(file, compress, origin)
file.seek(0, io.SEEK_END)
return len(self)
- def match(self, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType) -> bool:
+ def match(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType,
+ ) -> bool:
"""Returns ``True`` if this rdataset matches the specified class,
type, and covers.
"""
- if self.rdclass == rdclass and \
- self.rdtype == rdtype and \
- self.covers == covers:
+ if self.rdclass == rdclass and self.rdtype == rdtype and self.covers == covers:
return True
return False
def __init__(self, rdataset: Rdataset):
"""Create an immutable rdataset from the specified rdataset."""
- super().__init__(rdataset.rdclass, rdataset.rdtype, rdataset.covers,
- rdataset.ttl)
+ super().__init__(
+ rdataset.rdclass, rdataset.rdtype, rdataset.covers, rdataset.ttl
+ )
self.items = dns.immutable.Dict(rdataset.items)
def update_ttl(self, ttl):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def add(self, rd, ttl=None):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def union_update(self, other):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def intersection_update(self, other):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def update(self, other):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def __delitem__(self, i):
- raise TypeError('immutable')
+ raise TypeError("immutable")
# lgtm complains about these not raising ArithmeticError, but there is
# precedent for overrides of these methods in other classes to raise
# TypeError, and it seems like the better exception.
def __ior__(self, other): # lgtm[py/unexpected-raise-in-special-method]
- raise TypeError('immutable')
+ raise TypeError("immutable")
def __iand__(self, other): # lgtm[py/unexpected-raise-in-special-method]
- raise TypeError('immutable')
+ raise TypeError("immutable")
def __iadd__(self, other): # lgtm[py/unexpected-raise-in-special-method]
- raise TypeError('immutable')
+ raise TypeError("immutable")
def __isub__(self, other): # lgtm[py/unexpected-raise-in-special-method]
- raise TypeError('immutable')
+ raise TypeError("immutable")
def clear(self):
- raise TypeError('immutable')
+ raise TypeError("immutable")
def __copy__(self):
return ImmutableRdataset(super().copy())
return ImmutableRdataset(super().symmetric_difference(other))
-def from_text_list(rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- ttl: int, text_rdatas: Collection[str],
- idna_codec: Optional[dns.name.IDNACodec]=None,
- origin: Optional[dns.name.Name]=None,
- relativize: bool=True, relativize_to: Optional[dns.name.Name]=None) -> Rdataset:
+def from_text_list(
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ ttl: int,
+ text_rdatas: Collection[str],
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+) -> Rdataset:
"""Create an rdataset with the specified class, type, and TTL, and with
the specified list of rdatas in text format.
r = Rdataset(the_rdclass, the_rdtype)
r.update_ttl(ttl)
for t in text_rdatas:
- rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize,
- relativize_to, idna_codec)
+ rd = dns.rdata.from_text(
+ r.rdclass, r.rdtype, t, origin, relativize, relativize_to, idna_codec
+ )
r.add(rd)
return r
-def from_text(rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- ttl: int, *text_rdatas: Any) -> Rdataset:
+def from_text(
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ ttl: int,
+ *text_rdatas: Any,
+) -> Rdataset:
"""Create an rdataset with the specified class, type, and TTL, and with
the specified rdatas in text format.
import dns.enum
import dns.exception
+
class RdataType(dns.enum.IntEnum):
"""DNS Rdata Type"""
+
TYPE0 = 0
NONE = 0
A = 1
def _unknown_exception_class(cls):
return UnknownRdatatype
+
_registered_by_text: Dict[str, RdataType] = {}
_registered_by_value: Dict[RdataType, str] = {}
_metatypes = {RdataType.OPT}
-_singletons = {RdataType.SOA, RdataType.NXT, RdataType.DNAME,
- RdataType.NSEC, RdataType.CNAME}
+_singletons = {
+ RdataType.SOA,
+ RdataType.NXT,
+ RdataType.DNAME,
+ RdataType.NSEC,
+ RdataType.CNAME,
+}
class UnknownRdatatype(dns.exception.DNSException):
Returns a ``dns.rdatatype.RdataType``.
"""
- text = text.upper().replace('-', '_')
+ text = text.upper().replace("-", "_")
try:
return RdataType.from_text(text)
except UnknownRdatatype:
registered_text = _registered_by_value.get(value)
if registered_text:
text = registered_text
- return text.replace('_', '-')
+ return text.replace("_", "-")
def is_metatype(rdtype: RdataType) -> bool:
return True
return False
+
# pylint: disable=redefined-outer-name
-def register_type(rdtype: RdataType, rdtype_text: str, is_singleton: bool=False) -> None:
+def register_type(
+ rdtype: RdataType, rdtype_text: str, is_singleton: bool = False
+) -> None:
"""Dynamically register an rdatatype.
*rdtype*, a ``dns.rdatatype.RdataType``, the rdatatype to register.
if is_singleton:
_singletons.add(rdtype)
+
### BEGIN generated RdataType constants
TYPE0 = RdataType.TYPE0
class Relay(dns.rdtypes.util.Gateway):
- name = 'AMTRELAY relay'
+ name = "AMTRELAY relay"
@property
def relay(self):
# see: RFC 8777
- __slots__ = ['precedence', 'discovery_optional', 'relay_type', 'relay']
+ __slots__ = ["precedence", "discovery_optional", "relay_type", "relay"]
- def __init__(self, rdclass, rdtype, precedence, discovery_optional,
- relay_type, relay):
+ def __init__(
+ self, rdclass, rdtype, precedence, discovery_optional, relay_type, relay
+ ):
super().__init__(rdclass, rdtype)
relay = Relay(relay_type, relay)
self.precedence = self._as_uint8(precedence)
def to_text(self, origin=None, relativize=True, **kw):
relay = Relay(self.relay_type, self.relay).to_text(origin, relativize)
- return '%d %d %d %s' % (self.precedence, self.discovery_optional,
- self.relay_type, relay)
+ return "%d %d %d %s" % (
+ self.precedence,
+ self.discovery_optional,
+ self.relay_type,
+ relay,
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
precedence = tok.get_uint8()
discovery_optional = tok.get_uint8()
if discovery_optional > 1:
- raise dns.exception.SyntaxError('expecting 0 or 1')
+ raise dns.exception.SyntaxError("expecting 0 or 1")
discovery_optional = bool(discovery_optional)
relay_type = tok.get_uint8()
- if relay_type > 0x7f:
- raise dns.exception.SyntaxError('expecting an integer <= 127')
- relay = Relay.from_text(relay_type, tok, origin, relativize,
- relativize_to)
- return cls(rdclass, rdtype, precedence, discovery_optional, relay_type,
- relay.relay)
+ if relay_type > 0x7F:
+ raise dns.exception.SyntaxError("expecting an integer <= 127")
+ relay = Relay.from_text(relay_type, tok, origin, relativize, relativize_to)
+ return cls(
+ rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
relay_type = self.relay_type | (self.discovery_optional << 7)
header = struct.pack("!BB", self.precedence, relay_type)
file.write(header)
- Relay(self.relay_type, self.relay).to_wire(file, compress, origin,
- canonicalize)
+ Relay(self.relay_type, self.relay).to_wire(file, compress, origin, canonicalize)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (precedence, relay_type) = parser.get_struct('!BB')
+ (precedence, relay_type) = parser.get_struct("!BB")
discovery_optional = bool(relay_type >> 7)
- relay_type &= 0x7f
+ relay_type &= 0x7F
relay = Relay.from_wire_parser(relay_type, parser, origin)
- return cls(rdclass, rdtype, precedence, discovery_optional, relay_type,
- relay.relay)
+ return cls(
+ rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay
+ )
# see: RFC 6844
- __slots__ = ['flags', 'tag', 'value']
+ __slots__ = ["flags", "tag", "value"]
def __init__(self, rdclass, rdtype, flags, tag, value):
super().__init__(rdclass, rdtype)
self.value = self._as_bytes(value)
def to_text(self, origin=None, relativize=True, **kw):
- return '%u %s "%s"' % (self.flags,
- dns.rdata._escapify(self.tag),
- dns.rdata._escapify(self.value))
+ return '%u %s "%s"' % (
+ self.flags,
+ dns.rdata._escapify(self.tag),
+ dns.rdata._escapify(self.value),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
flags = tok.get_uint8()
tag = tok.get_string().encode()
value = tok.get_string().encode()
return cls(rdclass, rdtype, flags, tag, value)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!B', self.flags))
+ file.write(struct.pack("!B", self.flags))
l = len(self.tag)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.tag)
file.write(self.value)
import dns.immutable
# pylint: disable=unused-import
-from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 lgtm[py/unused-import]
+from dns.rdtypes.dnskeybase import (
+ SEP,
+ REVOKE,
+ ZONE,
+) # noqa: F401 lgtm[py/unused-import]
+
# pylint: enable=unused-import
+
@dns.immutable.immutable
class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):
import dns.tokenizer
_ctype_by_value = {
- 1: 'PKIX',
- 2: 'SPKI',
- 3: 'PGP',
- 4: 'IPKIX',
- 5: 'ISPKI',
- 6: 'IPGP',
- 7: 'ACPKIX',
- 8: 'IACPKIX',
- 253: 'URI',
- 254: 'OID',
+ 1: "PKIX",
+ 2: "SPKI",
+ 3: "PGP",
+ 4: "IPKIX",
+ 5: "ISPKI",
+ 6: "IPGP",
+ 7: "ACPKIX",
+ 8: "IACPKIX",
+ 253: "URI",
+ 254: "OID",
}
_ctype_by_name = {
- 'PKIX': 1,
- 'SPKI': 2,
- 'PGP': 3,
- 'IPKIX': 4,
- 'ISPKI': 5,
- 'IPGP': 6,
- 'ACPKIX': 7,
- 'IACPKIX': 8,
- 'URI': 253,
- 'OID': 254,
+ "PKIX": 1,
+ "SPKI": 2,
+ "PGP": 3,
+ "IPKIX": 4,
+ "ISPKI": 5,
+ "IPGP": 6,
+ "ACPKIX": 7,
+ "IACPKIX": 8,
+ "URI": 253,
+ "OID": 254,
}
# see RFC 4398
- __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate']
+ __slots__ = ["certificate_type", "key_tag", "algorithm", "certificate"]
- def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm,
- certificate):
+ def __init__(
+ self, rdclass, rdtype, certificate_type, key_tag, algorithm, certificate
+ ):
super().__init__(rdclass, rdtype)
self.certificate_type = self._as_uint16(certificate_type)
self.key_tag = self._as_uint16(key_tag)
def to_text(self, origin=None, relativize=True, **kw):
certificate_type = _ctype_to_text(self.certificate_type)
- return "%s %d %s %s" % (certificate_type, self.key_tag,
- dns.dnssectypes.Algorithm.to_text(self.algorithm),
- dns.rdata._base64ify(self.certificate, **kw))
+ return "%s %d %s %s" % (
+ certificate_type,
+ self.key_tag,
+ dns.dnssectypes.Algorithm.to_text(self.algorithm),
+ dns.rdata._base64ify(self.certificate, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
certificate_type = _ctype_from_text(tok.get_string())
key_tag = tok.get_uint16()
algorithm = dns.dnssectypes.Algorithm.from_text(tok.get_string())
b64 = tok.concatenate_remaining_identifiers().encode()
certificate = base64.b64decode(b64)
- return cls(rdclass, rdtype, certificate_type, key_tag,
- algorithm, certificate)
+ return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- prefix = struct.pack("!HHB", self.certificate_type, self.key_tag,
- self.algorithm)
+ prefix = struct.pack(
+ "!HHB", self.certificate_type, self.key_tag, self.algorithm
+ )
file.write(prefix)
file.write(self.certificate)
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
(certificate_type, key_tag, algorithm) = parser.get_struct("!HHB")
certificate = parser.get_remaining()
- return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
- certificate)
+ return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate)
@dns.immutable.immutable
class Bitmap(dns.rdtypes.util.Bitmap):
- type_name = 'CSYNC'
+ type_name = "CSYNC"
@dns.immutable.immutable
"""CSYNC record"""
- __slots__ = ['serial', 'flags', 'windows']
+ __slots__ = ["serial", "flags", "windows"]
def __init__(self, rdclass, rdtype, serial, flags, windows):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
text = Bitmap(self.windows).to_text()
- return '%d %d%s' % (self.serial, self.flags, text)
+ return "%d %d%s" % (self.serial, self.flags, text)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
serial = tok.get_uint32()
flags = tok.get_uint16()
bitmap = Bitmap.from_text(tok)
return cls(rdclass, rdtype, serial, flags, bitmap)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!IH', self.serial, self.flags))
+ file.write(struct.pack("!IH", self.serial, self.flags))
Bitmap(self.windows).to_wire(file)
@classmethod
import dns.immutable
# pylint: disable=unused-import
-from dns.rdtypes.dnskeybase import SEP, REVOKE, ZONE # noqa: F401 lgtm[py/unused-import]
+from dns.rdtypes.dnskeybase import (
+ SEP,
+ REVOKE,
+ ZONE,
+) # noqa: F401 lgtm[py/unused-import]
+
# pylint: enable=unused-import
+
@dns.immutable.immutable
class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):
def _validate_float_string(what):
if len(what) == 0:
raise dns.exception.FormError
- if what[0] == b'-'[0] or what[0] == b'+'[0]:
+ if what[0] == b"-"[0] or what[0] == b"+"[0]:
what = what[1:]
if what.isdigit():
return
try:
- (left, right) = what.split(b'.')
+ (left, right) = what.split(b".")
except ValueError:
raise dns.exception.FormError
- if left == b'' and right == b'':
+ if left == b"" and right == b"":
raise dns.exception.FormError
- if not left == b'' and not left.decode().isdigit():
+ if not left == b"" and not left.decode().isdigit():
raise dns.exception.FormError
- if not right == b'' and not right.decode().isdigit():
+ if not right == b"" and not right.decode().isdigit():
raise dns.exception.FormError
# see: RFC 1712
- __slots__ = ['latitude', 'longitude', 'altitude']
+ __slots__ = ["latitude", "longitude", "altitude"]
def __init__(self, rdclass, rdtype, latitude, longitude, altitude):
super().__init__(rdclass, rdtype)
- if isinstance(latitude, float) or \
- isinstance(latitude, int):
+ if isinstance(latitude, float) or isinstance(latitude, int):
latitude = str(latitude)
- if isinstance(longitude, float) or \
- isinstance(longitude, int):
+ if isinstance(longitude, float) or isinstance(longitude, int):
longitude = str(longitude)
- if isinstance(altitude, float) or \
- isinstance(altitude, int):
+ if isinstance(altitude, float) or isinstance(altitude, int):
altitude = str(altitude)
latitude = self._as_bytes(latitude, True, 255)
longitude = self._as_bytes(longitude, True, 255)
self.altitude = altitude
flat = self.float_latitude
if flat < -90.0 or flat > 90.0:
- raise dns.exception.FormError('bad latitude')
+ raise dns.exception.FormError("bad latitude")
flong = self.float_longitude
if flong < -180.0 or flong > 180.0:
- raise dns.exception.FormError('bad longitude')
+ raise dns.exception.FormError("bad longitude")
def to_text(self, origin=None, relativize=True, **kw):
- return '{} {} {}'.format(self.latitude.decode(),
- self.longitude.decode(),
- self.altitude.decode())
+ return "{} {} {}".format(
+ self.latitude.decode(), self.longitude.decode(), self.altitude.decode()
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
latitude = tok.get_string()
longitude = tok.get_string()
altitude = tok.get_string()
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.latitude)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.latitude)
l = len(self.longitude)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.longitude)
l = len(self.altitude)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.altitude)
@classmethod
# see: RFC 1035
- __slots__ = ['cpu', 'os']
+ __slots__ = ["cpu", "os"]
def __init__(self, rdclass, rdtype, cpu, os):
super().__init__(rdclass, rdtype)
self.os = self._as_bytes(os, True, 255)
def to_text(self, origin=None, relativize=True, **kw):
- return '"{}" "{}"'.format(dns.rdata._escapify(self.cpu),
- dns.rdata._escapify(self.os))
+ return '"{}" "{}"'.format(
+ dns.rdata._escapify(self.cpu), dns.rdata._escapify(self.os)
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
cpu = tok.get_string(max_length=255)
os = tok.get_string(max_length=255)
return cls(rdclass, rdtype, cpu, os)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.cpu)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.cpu)
l = len(self.os)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.os)
@classmethod
# see: RFC 5205
- __slots__ = ['hit', 'algorithm', 'key', 'servers']
+ __slots__ = ["hit", "algorithm", "key", "servers"]
def __init__(self, rdclass, rdtype, hit, algorithm, key, servers):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
hit = binascii.hexlify(self.hit).decode()
- key = base64.b64encode(self.key).replace(b'\n', b'').decode()
- text = ''
+ key = base64.b64encode(self.key).replace(b"\n", b"").decode()
+ text = ""
servers = []
for server in self.servers:
servers.append(server.choose_relativity(origin, relativize))
if len(servers) > 0:
- text += (' ' + ' '.join((x.to_unicode() for x in servers)))
- return '%u %s %s%s' % (self.algorithm, hit, key, text)
+ text += " " + " ".join((x.to_unicode() for x in servers))
+ return "%u %s %s%s" % (self.algorithm, hit, key, text)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_uint8()
hit = binascii.unhexlify(tok.get_string().encode())
key = base64.b64decode(tok.get_string().encode())
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (lh, algorithm, lk) = parser.get_struct('!BBH')
+ (lh, algorithm, lk) = parser.get_struct("!BBH")
hit = parser.get_bytes(lh)
key = parser.get_bytes(lk)
servers = []
# see: RFC 1183
- __slots__ = ['address', 'subaddress']
+ __slots__ = ["address", "subaddress"]
def __init__(self, rdclass, rdtype, address, subaddress):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
if self.subaddress:
- return '"{}" "{}"'.format(dns.rdata._escapify(self.address),
- dns.rdata._escapify(self.subaddress))
+ return '"{}" "{}"'.format(
+ dns.rdata._escapify(self.address), dns.rdata._escapify(self.subaddress)
+ )
else:
return '"%s"' % dns.rdata._escapify(self.address)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_string()
tokens = tok.get_remaining(max_tokens=1)
if len(tokens) >= 1:
subaddress = tokens[0].unescape().value
else:
- subaddress = ''
+ subaddress = ""
return cls(rdclass, rdtype, address, subaddress)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.address)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.address)
l = len(self.subaddress)
if l > 0:
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.subaddress)
@classmethod
if parser.remaining() > 0:
subaddress = parser.get_counted_bytes()
else:
- subaddress = b''
+ subaddress = b""
return cls(rdclass, rdtype, address, subaddress)
# see: rfc6742.txt
- __slots__ = ['preference', 'locator32']
+ __slots__ = ["preference", "locator32"]
def __init__(self, rdclass, rdtype, preference, locator32):
super().__init__(rdclass, rdtype)
self.locator32 = self._as_ipv4_address(locator32)
def to_text(self, origin=None, relativize=True, **kw):
- return f'{self.preference} {self.locator32}'
+ return f"{self.preference} {self.locator32}"
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
nodeid = tok.get_identifier()
return cls(rdclass, rdtype, preference, nodeid)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!H', self.preference))
+ file.write(struct.pack("!H", self.preference))
file.write(dns.ipv4.inet_aton(self.locator32))
@classmethod
# see: rfc6742.txt
- __slots__ = ['preference', 'locator64']
+ __slots__ = ["preference", "locator64"]
def __init__(self, rdclass, rdtype, preference, locator64):
super().__init__(rdclass, rdtype)
self.preference = self._as_uint16(preference)
if isinstance(locator64, bytes):
if len(locator64) != 8:
- raise ValueError('invalid locator64')
- self.locator64 = dns.rdata._hexify(locator64, 4, b':')
+ raise ValueError("invalid locator64")
+ self.locator64 = dns.rdata._hexify(locator64, 4, b":")
else:
- dns.rdtypes.util.parse_formatted_hex(locator64, 4, 4, ':')
+ dns.rdtypes.util.parse_formatted_hex(locator64, 4, 4, ":")
self.locator64 = locator64
def to_text(self, origin=None, relativize=True, **kw):
- return f'{self.preference} {self.locator64}'
+ return f"{self.preference} {self.locator64}"
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
locator64 = tok.get_identifier()
return cls(rdclass, rdtype, preference, locator64)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!H', self.preference))
- file.write(dns.rdtypes.util.parse_formatted_hex(self.locator64,
- 4, 4, ':'))
+ file.write(struct.pack("!H", self.preference))
+ file.write(dns.rdtypes.util.parse_formatted_hex(self.locator64, 4, 4, ":"))
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
def _check_coordinate_list(value, low, high):
if value[0] < low or value[0] > high:
- raise ValueError(f'not in range [{low}, {high}]')
+ raise ValueError(f"not in range [{low}, {high}]")
if value[1] < 0 or value[1] > 59:
- raise ValueError('bad minutes value')
+ raise ValueError("bad minutes value")
if value[2] < 0 or value[2] > 59:
- raise ValueError('bad seconds value')
+ raise ValueError("bad seconds value")
if value[3] < 0 or value[3] > 999:
- raise ValueError('bad milliseconds value')
+ raise ValueError("bad milliseconds value")
if value[4] != 1 and value[4] != -1:
- raise ValueError('bad hemisphere value')
+ raise ValueError("bad hemisphere value")
@dns.immutable.immutable
# see: RFC 1876
- __slots__ = ['latitude', 'longitude', 'altitude', 'size',
- 'horizontal_precision', 'vertical_precision']
-
- def __init__(self, rdclass, rdtype, latitude, longitude, altitude,
- size=_default_size, hprec=_default_hprec,
- vprec=_default_vprec):
+ __slots__ = [
+ "latitude",
+ "longitude",
+ "altitude",
+ "size",
+ "horizontal_precision",
+ "vertical_precision",
+ ]
+
+ def __init__(
+ self,
+ rdclass,
+ rdtype,
+ latitude,
+ longitude,
+ altitude,
+ 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
def to_text(self, origin=None, relativize=True, **kw):
if self.latitude[4] > 0:
- lat_hemisphere = 'N'
+ lat_hemisphere = "N"
else:
- lat_hemisphere = 'S'
+ lat_hemisphere = "S"
if self.longitude[4] > 0:
- long_hemisphere = 'E'
+ long_hemisphere = "E"
else:
- long_hemisphere = 'W'
+ long_hemisphere = "W"
text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % (
- self.latitude[0], self.latitude[1],
- self.latitude[2], self.latitude[3], lat_hemisphere,
- self.longitude[0], self.longitude[1], self.longitude[2],
- self.longitude[3], long_hemisphere,
- self.altitude / 100.0
+ self.latitude[0],
+ self.latitude[1],
+ self.latitude[2],
+ self.latitude[3],
+ lat_hemisphere,
+ self.longitude[0],
+ 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:
+ if (
+ self.size != _default_size
+ or self.horizontal_precision != _default_hprec
+ or self.vertical_precision != _default_vprec
+ ):
text += " {:0.2f}m {:0.2f}m {:0.2f}m".format(
- self.size / 100.0, self.horizontal_precision / 100.0,
- self.vertical_precision / 100.0
+ self.size / 100.0,
+ self.horizontal_precision / 100.0,
+ self.vertical_precision / 100.0,
)
return text
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
latitude = [0, 0, 0, 0, 1]
longitude = [0, 0, 0, 0, 1]
size = _default_size
if t.isdigit():
latitude[1] = int(t)
t = tok.get_string()
- if '.' in t:
- (seconds, milliseconds) = t.split('.')
+ 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)
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:
elif t.isdigit():
latitude[2] = int(t)
t = tok.get_string()
- if t == 'S':
+ if t == "S":
latitude[4] = -1
- elif t != 'N':
- raise dns.exception.SyntaxError('bad latitude hemisphere value')
+ elif t != "N":
+ raise dns.exception.SyntaxError("bad latitude hemisphere value")
longitude[0] = tok.get_int()
t = tok.get_string()
if t.isdigit():
longitude[1] = int(t)
t = tok.get_string()
- if '.' in t:
- (seconds, milliseconds) = t.split('.')
+ 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)
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:
elif t.isdigit():
longitude[2] = int(t)
t = tok.get_string()
- if t == 'W':
+ if t == "W":
longitude[4] = -1
- elif t != 'E':
- raise dns.exception.SyntaxError('bad longitude hemisphere value')
+ elif t != "E":
+ raise dns.exception.SyntaxError("bad longitude hemisphere value")
t = tok.get_string()
- if t[-1] == 'm':
- t = t[0: -1]
- altitude = float(t) * 100.0 # m -> cm
+ if t[-1] == "m":
+ t = t[0:-1]
+ altitude = float(t) * 100.0 # m -> cm
tokens = tok.get_remaining(max_tokens=3)
if len(tokens) >= 1:
value = tokens[0].unescape().value
- if value[-1] == 'm':
- value = value[0: -1]
- size = float(value) * 100.0 # m -> cm
+ if value[-1] == "m":
+ value = value[0:-1]
+ size = float(value) * 100.0 # m -> cm
if len(tokens) >= 2:
value = tokens[1].unescape().value
- if value[-1] == 'm':
- value = value[0: -1]
- hprec = float(value) * 100.0 # m -> cm
+ if value[-1] == "m":
+ value = value[0:-1]
+ hprec = float(value) * 100.0 # m -> cm
if len(tokens) >= 3:
value = tokens[2].unescape().value
- if value[-1] == 'm':
- value = value[0: -1]
- vprec = float(value) * 100.0 # m -> cm
+ if value[-1] == "m":
+ value = value[0:-1]
+ vprec = float(value) * 100.0 # m -> cm
# Try encoding these now so we raise if they are bad
_encode_size(size, "size")
_encode_size(hprec, "horizontal precision")
_encode_size(vprec, "vertical precision")
- return cls(rdclass, rdtype, latitude, longitude, altitude,
- size, hprec, vprec)
+ return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- milliseconds = (self.latitude[0] * 3600000 +
- self.latitude[1] * 60000 +
- self.latitude[2] * 1000 +
- self.latitude[3]) * self.latitude[4]
+ milliseconds = (
+ self.latitude[0] * 3600000
+ + self.latitude[1] * 60000
+ + self.latitude[2] * 1000
+ + self.latitude[3]
+ ) * self.latitude[4]
latitude = 0x80000000 + milliseconds
- milliseconds = (self.longitude[0] * 3600000 +
- self.longitude[1] * 60000 +
- self.longitude[2] * 1000 +
- self.longitude[3]) * self.longitude[4]
+ milliseconds = (
+ self.longitude[0] * 3600000
+ + self.longitude[1] * 60000
+ + self.longitude[2] * 1000
+ + self.longitude[3]
+ ) * self.longitude[4]
longitude = 0x80000000 + milliseconds
altitude = int(self.altitude) + 10000000
size = _encode_size(self.size, "size")
hprec = _encode_size(self.horizontal_precision, "horizontal precision")
vprec = _encode_size(self.vertical_precision, "vertical precision")
- wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude,
- longitude, altitude)
+ wire = struct.pack(
+ "!BBBBIII", 0, size, hprec, vprec, latitude, longitude, altitude
+ )
file.write(wire)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (version, size, hprec, vprec, latitude, longitude, altitude) = \
- parser.get_struct("!BBBBIII")
+ (
+ version,
+ size,
+ hprec,
+ vprec,
+ latitude,
+ longitude,
+ altitude,
+ ) = parser.get_struct("!BBBBIII")
if version != 0:
raise dns.exception.FormError("LOC version not zero")
if latitude < _MIN_LATITUDE or latitude > _MAX_LATITUDE:
size = _decode_size(size, "size")
hprec = _decode_size(hprec, "horizontal precision")
vprec = _decode_size(vprec, "vertical precision")
- return cls(rdclass, rdtype, latitude, longitude, altitude,
- size, hprec, vprec)
+ return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec)
@property
def float_latitude(self):
# see: rfc6742.txt
- __slots__ = ['preference', 'fqdn']
+ __slots__ = ["preference", "fqdn"]
def __init__(self, rdclass, rdtype, preference, fqdn):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
fqdn = self.fqdn.choose_relativity(origin, relativize)
- return '%d %s' % (self.preference, fqdn)
+ return "%d %s" % (self.preference, fqdn)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
fqdn = tok.get_name(origin, relativize, relativize_to)
return cls(rdclass, rdtype, preference, fqdn)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!H', self.preference))
+ file.write(struct.pack("!H", self.preference))
self.fqdn.to_wire(file, compress, origin, canonicalize)
@classmethod
# see: rfc6742.txt
- __slots__ = ['preference', 'nodeid']
+ __slots__ = ["preference", "nodeid"]
def __init__(self, rdclass, rdtype, preference, nodeid):
super().__init__(rdclass, rdtype)
self.preference = self._as_uint16(preference)
if isinstance(nodeid, bytes):
if len(nodeid) != 8:
- raise ValueError('invalid nodeid')
- self.nodeid = dns.rdata._hexify(nodeid, 4, b':')
+ raise ValueError("invalid nodeid")
+ self.nodeid = dns.rdata._hexify(nodeid, 4, b":")
else:
- dns.rdtypes.util.parse_formatted_hex(nodeid, 4, 4, ':')
+ dns.rdtypes.util.parse_formatted_hex(nodeid, 4, 4, ":")
self.nodeid = nodeid
def to_text(self, origin=None, relativize=True, **kw):
- return f'{self.preference} {self.nodeid}'
+ return f"{self.preference} {self.nodeid}"
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
nodeid = tok.get_identifier()
return cls(rdclass, rdtype, preference, nodeid)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- file.write(struct.pack('!H', self.preference))
- file.write(dns.rdtypes.util.parse_formatted_hex(self.nodeid, 4, 4, ':'))
+ file.write(struct.pack("!H", self.preference))
+ file.write(dns.rdtypes.util.parse_formatted_hex(self.nodeid, 4, 4, ":"))
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
@dns.immutable.immutable
class Bitmap(dns.rdtypes.util.Bitmap):
- type_name = 'NSEC'
+ type_name = "NSEC"
@dns.immutable.immutable
"""NSEC record"""
- __slots__ = ['next', 'windows']
+ __slots__ = ["next", "windows"]
def __init__(self, rdclass, rdtype, next, windows):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
next = self.next.choose_relativity(origin, relativize)
text = Bitmap(self.windows).to_text()
- return '{}{}'.format(next, text)
+ return "{}{}".format(next, text)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
next = tok.get_name(origin, relativize, relativize_to)
windows = Bitmap.from_text(tok)
return cls(rdclass, rdtype, next, windows)
import dns.rdtypes.util
-b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV',
- b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
-b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
- b'0123456789ABCDEFGHIJKLMNOPQRSTUV')
+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
@dns.immutable.immutable
class Bitmap(dns.rdtypes.util.Bitmap):
- type_name = 'NSEC3'
+ type_name = "NSEC3"
@dns.immutable.immutable
"""NSEC3 record"""
- __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows']
+ __slots__ = ["algorithm", "flags", "iterations", "salt", "next", "windows"]
- def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt,
- next, windows):
+ def __init__(
+ self, rdclass, rdtype, algorithm, flags, iterations, salt, next, windows
+ ):
super().__init__(rdclass, rdtype)
self.algorithm = self._as_uint8(algorithm)
self.flags = self._as_uint8(flags)
self.windows = tuple(windows.windows)
def to_text(self, origin=None, relativize=True, **kw):
- next = base64.b32encode(self.next).translate(
- b32_normal_to_hex).lower().decode()
- if self.salt == b'':
- salt = '-'
+ next = base64.b32encode(self.next).translate(b32_normal_to_hex).lower().decode()
+ if self.salt == b"":
+ salt = "-"
else:
salt = binascii.hexlify(self.salt).decode()
text = Bitmap(self.windows).to_text()
- return '%u %u %u %s %s%s' % (self.algorithm, self.flags,
- self.iterations, salt, next, text)
+ return "%u %u %u %s %s%s" % (
+ self.algorithm,
+ self.flags,
+ self.iterations,
+ salt,
+ next,
+ text,
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_uint8()
flags = tok.get_uint8()
iterations = tok.get_uint16()
salt = tok.get_string()
- if salt == '-':
- salt = b''
+ if salt == "-":
+ salt = b""
else:
- salt = binascii.unhexlify(salt.encode('ascii'))
- next = tok.get_string().encode(
- 'ascii').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)
bitmap = Bitmap.from_text(tok)
- return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
- bitmap)
+ return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.salt)
- file.write(struct.pack("!BBHB", self.algorithm, self.flags,
- self.iterations, l))
+ file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l))
file.write(self.salt)
l = len(self.next)
file.write(struct.pack("!B", l))
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (algorithm, flags, iterations) = parser.get_struct('!BBH')
+ (algorithm, flags, iterations) = parser.get_struct("!BBH")
salt = parser.get_counted_bytes()
next = parser.get_counted_bytes()
bitmap = Bitmap.from_wire_parser(parser)
- return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
- bitmap)
+ return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap)
"""NSEC3PARAM record"""
- __slots__ = ['algorithm', 'flags', 'iterations', 'salt']
+ __slots__ = ["algorithm", "flags", "iterations", "salt"]
def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt):
super().__init__(rdclass, rdtype)
self.salt = self._as_bytes(salt, True, 255)
def to_text(self, origin=None, relativize=True, **kw):
- if self.salt == b'':
- salt = '-'
+ if self.salt == b"":
+ salt = "-"
else:
salt = binascii.hexlify(self.salt).decode()
- return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations,
- salt)
+ return "%u %u %u %s" % (self.algorithm, self.flags, self.iterations, salt)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_uint8()
flags = tok.get_uint8()
iterations = tok.get_uint16()
salt = tok.get_string()
- if salt == '-':
- salt = ''
+ if salt == "-":
+ salt = ""
else:
salt = binascii.unhexlify(salt.encode())
return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.salt)
- file.write(struct.pack("!BBHB", self.algorithm, self.flags,
- self.iterations, l))
+ file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l))
file.write(self.salt)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (algorithm, flags, iterations) = parser.get_struct('!BBH')
+ (algorithm, flags, iterations) = parser.get_struct("!BBH")
salt = parser.get_counted_bytes()
return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
import dns.rdata
import dns.tokenizer
+
@dns.immutable.immutable
class OPENPGPKEY(dns.rdata.Rdata):
return dns.rdata._base64ify(self.key, chunksize=None, **kw)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
b64 = tok.concatenate_remaining_identifiers().encode()
key = base64.b64decode(b64)
return cls(rdclass, rdtype, key)
# We don't implement from_text, and that's ok.
# pylint: disable=abstract-method
+
@dns.immutable.immutable
class OPT(dns.rdata.Rdata):
"""OPT record"""
- __slots__ = ['options']
+ __slots__ = ["options"]
def __init__(self, rdclass, rdtype, options):
"""Initialize an OPT rdata.
"""
super().__init__(rdclass, rdtype)
+
def as_option(option):
if not isinstance(option, dns.edns.Option):
- raise ValueError('option is not a dns.edns.option')
+ raise ValueError("option is not a dns.edns.option")
return option
+
self.options = self._as_tuple(options, as_option)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
file.write(owire)
def to_text(self, origin=None, relativize=True, **kw):
- return ' '.join(opt.to_text() for opt in self.options)
+ return " ".join(opt.to_text() for opt in self.options)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
options = []
while parser.remaining() > 0:
- (otype, olen) = parser.get_struct('!HH')
+ (otype, olen) = parser.get_struct("!HH")
with parser.restrict_to(olen):
opt = dns.edns.option_from_wire_parser(otype, parser)
options.append(opt)
# see: RFC 1183
- __slots__ = ['mbox', 'txt']
+ __slots__ = ["mbox", "txt"]
def __init__(self, rdclass, rdtype, mbox, txt):
super().__init__(rdclass, rdtype)
return "{} {}".format(str(mbox), str(txt))
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
mbox = tok.get_name(origin, relativize, relativize_to)
txt = tok.get_name(origin, relativize, relativize_to)
return cls(rdclass, rdtype, mbox, txt)
hour = int(what[8:10])
minute = int(what[10:12])
second = int(what[12:14])
- return calendar.timegm((year, month, day, hour, minute, second,
- 0, 0, 0))
+ 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))
+ return time.strftime("%Y%m%d%H%M%S", time.gmtime(what))
@dns.immutable.immutable
"""RRSIG record"""
- __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl',
- 'expiration', 'inception', 'key_tag', 'signer',
- 'signature']
-
- def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
- original_ttl, expiration, inception, key_tag, signer,
- signature):
+ __slots__ = [
+ "type_covered",
+ "algorithm",
+ "labels",
+ "original_ttl",
+ "expiration",
+ "inception",
+ "key_tag",
+ "signer",
+ "signature",
+ ]
+
+ def __init__(
+ self,
+ rdclass,
+ rdtype,
+ type_covered,
+ algorithm,
+ labels,
+ original_ttl,
+ expiration,
+ inception,
+ key_tag,
+ signer,
+ signature,
+ ):
super().__init__(rdclass, rdtype)
self.type_covered = self._as_rdatatype(type_covered)
self.algorithm = dns.dnssectypes.Algorithm.make(algorithm)
return self.type_covered
def to_text(self, origin=None, relativize=True, **kw):
- return '%s %d %d %d %s %s %d %s %s' % (
+ return "%s %d %d %d %s %s %d %s %s" % (
dns.rdatatype.to_text(self.type_covered),
self.algorithm,
self.labels,
posixtime_to_sigtime(self.inception),
self.key_tag,
self.signer.choose_relativity(origin, relativize),
- dns.rdata._base64ify(self.signature, **kw)
+ dns.rdata._base64ify(self.signature, **kw),
)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
type_covered = dns.rdatatype.from_text(tok.get_string())
algorithm = dns.dnssectypes.Algorithm.from_text(tok.get_string())
labels = tok.get_int()
signer = tok.get_name(origin, relativize, relativize_to)
b64 = tok.concatenate_remaining_identifiers().encode()
signature = base64.b64decode(b64)
- return cls(rdclass, rdtype, type_covered, algorithm, labels,
- original_ttl, expiration, inception, key_tag, signer,
- signature)
+ return cls(
+ rdclass,
+ rdtype,
+ type_covered,
+ algorithm,
+ labels,
+ original_ttl,
+ expiration,
+ inception,
+ key_tag,
+ signer,
+ signature,
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- header = struct.pack('!HBBIIIH', self.type_covered,
- self.algorithm, self.labels,
- self.original_ttl, self.expiration,
- self.inception, self.key_tag)
+ header = struct.pack(
+ "!HBBIIIH",
+ self.type_covered,
+ self.algorithm,
+ self.labels,
+ self.original_ttl,
+ self.expiration,
+ self.inception,
+ self.key_tag,
+ )
file.write(header)
self.signer.to_wire(file, None, origin, canonicalize)
file.write(self.signature)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- header = parser.get_struct('!HBBIIIH')
+ header = parser.get_struct("!HBBIIIH")
signer = parser.get_name(origin)
signature = parser.get_remaining()
return cls(rdclass, rdtype, *header, signer, signature)
# see: RFC 1035
- __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire',
- 'minimum']
+ __slots__ = ["mname", "rname", "serial", "refresh", "retry", "expire", "minimum"]
- def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry,
- expire, minimum):
+ def __init__(
+ self, rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum
+ ):
super().__init__(rdclass, rdtype)
self.mname = self._as_name(mname)
self.rname = self._as_name(rname)
def to_text(self, origin=None, relativize=True, **kw):
mname = self.mname.choose_relativity(origin, relativize)
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)
+ return "%s %s %d %d %d %d %d" % (
+ mname,
+ rname,
+ self.serial,
+ self.refresh,
+ self.retry,
+ self.expire,
+ self.minimum,
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
mname = tok.get_name(origin, relativize, relativize_to)
rname = tok.get_name(origin, relativize, relativize_to)
serial = tok.get_uint32()
retry = tok.get_ttl()
expire = tok.get_ttl()
minimum = tok.get_ttl()
- return cls(rdclass, rdtype, mname, rname, serial, refresh, retry,
- expire, minimum)
+ return cls(
+ rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
self.mname.to_wire(file, compress, origin, canonicalize)
self.rname.to_wire(file, compress, origin, canonicalize)
- five_ints = struct.pack('!IIIII', self.serial, self.refresh,
- self.retry, self.expire, self.minimum)
+ five_ints = struct.pack(
+ "!IIIII", self.serial, self.refresh, self.retry, self.expire, self.minimum
+ )
file.write(five_ints)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
mname = parser.get_name(origin)
rname = parser.get_name(origin)
- return cls(rdclass, rdtype, mname, rname, *parser.get_struct('!IIIII'))
+ return cls(rdclass, rdtype, mname, rname, *parser.get_struct("!IIIII"))
# See RFC 4255
- __slots__ = ['algorithm', 'fp_type', 'fingerprint']
+ __slots__ = ["algorithm", "fp_type", "fingerprint"]
- def __init__(self, rdclass, rdtype, algorithm, fp_type,
- fingerprint):
+ def __init__(self, rdclass, rdtype, algorithm, fp_type, fingerprint):
super().__init__(rdclass, rdtype)
self.algorithm = self._as_uint8(algorithm)
self.fp_type = self._as_uint8(fp_type)
def to_text(self, origin=None, relativize=True, **kw):
kw = kw.copy()
- chunksize = kw.pop('chunksize', 128)
- return '%d %d %s' % (self.algorithm,
- self.fp_type,
- dns.rdata._hexify(self.fingerprint,
- chunksize=chunksize,
- **kw))
+ chunksize = kw.pop("chunksize", 128)
+ return "%d %d %s" % (
+ self.algorithm,
+ self.fp_type,
+ dns.rdata._hexify(self.fingerprint, chunksize=chunksize, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_uint8()
fp_type = tok.get_uint8()
fingerprint = tok.concatenate_remaining_identifiers().encode()
"""TKEY Record"""
- __slots__ = ['algorithm', 'inception', 'expiration', 'mode', 'error',
- 'key', 'other']
-
- def __init__(self, rdclass, rdtype, algorithm, inception, expiration,
- mode, error, key, other=b''):
+ __slots__ = [
+ "algorithm",
+ "inception",
+ "expiration",
+ "mode",
+ "error",
+ "key",
+ "other",
+ ]
+
+ def __init__(
+ self,
+ rdclass,
+ rdtype,
+ algorithm,
+ inception,
+ expiration,
+ mode,
+ error,
+ key,
+ other=b"",
+ ):
super().__init__(rdclass, rdtype)
self.algorithm = self._as_name(algorithm)
self.inception = self._as_uint32(inception)
def to_text(self, origin=None, relativize=True, **kw):
_algorithm = self.algorithm.choose_relativity(origin, relativize)
- text = '%s %u %u %u %u %s' % (str(_algorithm), self.inception,
- self.expiration, self.mode, self.error,
- dns.rdata._base64ify(self.key, 0))
+ text = "%s %u %u %u %u %s" % (
+ str(_algorithm),
+ self.inception,
+ self.expiration,
+ self.mode,
+ self.error,
+ dns.rdata._base64ify(self.key, 0),
+ )
if len(self.other) > 0:
- text += ' %s' % (dns.rdata._base64ify(self.other, 0))
+ text += " %s" % (dns.rdata._base64ify(self.other, 0))
return text
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_name(relativize=False)
inception = tok.get_uint32()
expiration = tok.get_uint32()
other_b64 = tok.concatenate_remaining_identifiers(True).encode()
other = base64.b64decode(other_b64)
- return cls(rdclass, rdtype, algorithm, inception, expiration, mode,
- error, key, other)
+ return cls(
+ rdclass, rdtype, algorithm, inception, expiration, mode, error, key, other
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
self.algorithm.to_wire(file, compress, origin)
- file.write(struct.pack("!IIHH", self.inception, self.expiration,
- self.mode, self.error))
+ file.write(
+ struct.pack("!IIHH", self.inception, self.expiration, self.mode, self.error)
+ )
file.write(struct.pack("!H", len(self.key)))
file.write(self.key)
file.write(struct.pack("!H", len(self.other)))
key = parser.get_counted_bytes(2)
other = parser.get_counted_bytes(2)
- return cls(rdclass, rdtype, algorithm, inception, expiration, mode,
- error, key, other)
+ return cls(
+ rdclass, rdtype, algorithm, inception, expiration, mode, error, key, other
+ )
# Constants for the mode field - from RFC 2930:
# 2.5 The Mode Field
"""TSIG record"""
- __slots__ = ['algorithm', 'time_signed', 'fudge', 'mac',
- 'original_id', 'error', 'other']
-
- def __init__(self, rdclass, rdtype, algorithm, time_signed, fudge, mac,
- original_id, error, other):
+ __slots__ = [
+ "algorithm",
+ "time_signed",
+ "fudge",
+ "mac",
+ "original_id",
+ "error",
+ "other",
+ ]
+
+ def __init__(
+ self,
+ rdclass,
+ rdtype,
+ algorithm,
+ time_signed,
+ fudge,
+ mac,
+ original_id,
+ error,
+ other,
+ ):
"""Initialize a TSIG rdata.
*rdclass*, an ``int`` is the rdataclass of the Rdata.
def to_text(self, origin=None, relativize=True, **kw):
algorithm = self.algorithm.choose_relativity(origin, relativize)
error = dns.rcode.to_text(self.error, True)
- text = f"{algorithm} {self.time_signed} {self.fudge} " + \
- f"{len(self.mac)} {dns.rdata._base64ify(self.mac, 0)} " + \
- f"{self.original_id} {error} {len(self.other)}"
+ text = (
+ f"{algorithm} {self.time_signed} {self.fudge} "
+ + f"{len(self.mac)} {dns.rdata._base64ify(self.mac, 0)} "
+ + f"{self.original_id} {error} {len(self.other)}"
+ )
if self.other:
text += f" {dns.rdata._base64ify(self.other, 0)}"
return text
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
algorithm = tok.get_name(relativize=False)
time_signed = tok.get_uint48()
fudge = tok.get_uint16()
mac_len = tok.get_uint16()
mac = base64.b64decode(tok.get_string())
if len(mac) != mac_len:
- raise SyntaxError('invalid MAC')
+ raise SyntaxError("invalid MAC")
original_id = tok.get_uint16()
error = dns.rcode.from_text(tok.get_string())
other_len = tok.get_uint16()
if other_len > 0:
other = base64.b64decode(tok.get_string())
if len(other) != other_len:
- raise SyntaxError('invalid other data')
+ raise SyntaxError("invalid other data")
else:
- other = b''
- return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac,
- original_id, error, other)
+ other = b""
+ return cls(
+ rdclass,
+ rdtype,
+ algorithm,
+ time_signed,
+ fudge,
+ mac,
+ original_id,
+ error,
+ other,
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
self.algorithm.to_wire(file, None, origin, False)
- file.write(struct.pack('!HIHH',
- (self.time_signed >> 32) & 0xffff,
- self.time_signed & 0xffffffff,
- self.fudge,
- len(self.mac)))
+ file.write(
+ struct.pack(
+ "!HIHH",
+ (self.time_signed >> 32) & 0xFFFF,
+ self.time_signed & 0xFFFFFFFF,
+ self.fudge,
+ len(self.mac),
+ )
+ )
file.write(self.mac)
- file.write(struct.pack('!HHH', self.original_id, self.error,
- len(self.other)))
+ file.write(struct.pack("!HHH", self.original_id, self.error, len(self.other)))
file.write(self.other)
@classmethod
time_signed = parser.get_uint48()
fudge = parser.get_uint16()
mac = parser.get_counted_bytes(2)
- (original_id, error) = parser.get_struct('!HH')
+ (original_id, error) = parser.get_struct("!HH")
other = parser.get_counted_bytes(2)
- return cls(rdclass, rdtype, algorithm, time_signed, fudge, mac,
- original_id, error, other)
+ return cls(
+ rdclass,
+ rdtype,
+ algorithm,
+ time_signed,
+ fudge,
+ mac,
+ original_id,
+ error,
+ other,
+ )
# see RFC 7553
- __slots__ = ['priority', 'weight', 'target']
+ __slots__ = ["priority", "weight", "target"]
def __init__(self, rdclass, rdtype, priority, weight, target):
super().__init__(rdclass, rdtype)
raise dns.exception.SyntaxError("URI target cannot be empty")
def to_text(self, origin=None, relativize=True, **kw):
- return '%d %d "%s"' % (self.priority, self.weight,
- self.target.decode())
+ return '%d %d "%s"' % (self.priority, self.weight, self.target.decode())
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
priority = tok.get_uint16()
weight = tok.get_uint16()
target = tok.get().unescape()
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (priority, weight) = parser.get_struct('!HH')
+ (priority, weight) = parser.get_struct("!HH")
target = parser.get_remaining()
if len(target) == 0:
- raise dns.exception.FormError('URI target may not be empty')
+ raise dns.exception.FormError("URI target may not be empty")
return cls(rdclass, rdtype, priority, weight, target)
def _processing_priority(self):
# see RFC 1183
- __slots__ = ['address']
+ __slots__ = ["address"]
def __init__(self, rdclass, rdtype, address):
super().__init__(rdclass, rdtype)
return '"%s"' % dns.rdata._escapify(self.address)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_string()
return cls(rdclass, rdtype, address)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.address)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(self.address)
@classmethod
# See RFC 8976
- __slots__ = ['serial', 'scheme', 'hash_algorithm', 'digest']
+ __slots__ = ["serial", "scheme", "hash_algorithm", "digest"]
def __init__(self, rdclass, rdtype, serial, scheme, hash_algorithm, digest):
super().__init__(rdclass, rdtype)
self.digest = self._as_bytes(digest)
if self.scheme == 0: # reserved, RFC 8976 Sec. 5.2
- raise ValueError('scheme 0 is reserved')
+ raise ValueError("scheme 0 is reserved")
if self.hash_algorithm == 0: # reserved, RFC 8976 Sec. 5.3
- raise ValueError('hash_algorithm 0 is reserved')
+ raise ValueError("hash_algorithm 0 is reserved")
hasher = dns.zonetypes._digest_hashers.get(self.hash_algorithm)
if hasher and hasher().digest_size != len(self.digest):
- raise ValueError('digest length inconsistent with hash algorithm')
+ raise ValueError("digest length inconsistent with hash algorithm")
def to_text(self, origin=None, relativize=True, **kw):
kw = kw.copy()
- chunksize = kw.pop('chunksize', 128)
- return '%d %d %d %s' % (self.serial, self.scheme, self.hash_algorithm,
- dns.rdata._hexify(self.digest,
- chunksize=chunksize,
- **kw))
+ chunksize = kw.pop("chunksize", 128)
+ return "%d %d %d %s" % (
+ self.serial,
+ self.scheme,
+ self.hash_algorithm,
+ dns.rdata._hexify(self.digest, chunksize=chunksize, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
serial = tok.get_uint32()
scheme = tok.get_uint8()
hash_algorithm = tok.get_uint8()
return cls(rdclass, rdtype, serial, scheme, hash_algorithm, digest)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- header = struct.pack("!IBB", self.serial, self.scheme,
- self.hash_algorithm)
+ header = struct.pack("!IBB", self.serial, self.scheme, self.hash_algorithm)
file.write(header)
file.write(self.digest)
"""Class ANY (generic) rdata type classes."""
__all__ = [
- 'AFSDB',
- 'AMTRELAY',
- 'AVC',
- 'CAA',
- 'CDNSKEY',
- 'CDS',
- 'CERT',
- 'CNAME',
- 'CSYNC',
- 'DLV',
- 'DNAME',
- 'DNSKEY',
- 'DS',
- 'EUI48',
- 'EUI64',
- 'GPOS',
- 'HINFO',
- 'HIP',
- 'ISDN',
- 'L32',
- 'L64',
- 'LOC',
- 'LP',
- 'MX',
- 'NID',
- 'NINFO',
- 'NS',
- 'NSEC',
- 'NSEC3',
- 'NSEC3PARAM',
- 'OPENPGPKEY',
- 'OPT',
- 'PTR',
- 'RP',
- 'RRSIG',
- 'RT',
- 'SMIMEA',
- 'SOA',
- 'SPF',
- 'SSHFP',
- 'TKEY',
- 'TLSA',
- 'TSIG',
- 'TXT',
- 'URI',
- 'X25',
- 'ZONEMD',
+ "AFSDB",
+ "AMTRELAY",
+ "AVC",
+ "CAA",
+ "CDNSKEY",
+ "CDS",
+ "CERT",
+ "CNAME",
+ "CSYNC",
+ "DLV",
+ "DNAME",
+ "DNSKEY",
+ "DS",
+ "EUI48",
+ "EUI64",
+ "GPOS",
+ "HINFO",
+ "HIP",
+ "ISDN",
+ "L32",
+ "L64",
+ "LOC",
+ "LP",
+ "MX",
+ "NID",
+ "NINFO",
+ "NS",
+ "NSEC",
+ "NSEC3",
+ "NSEC3PARAM",
+ "OPENPGPKEY",
+ "OPT",
+ "PTR",
+ "RP",
+ "RRSIG",
+ "RT",
+ "SMIMEA",
+ "SOA",
+ "SPF",
+ "SSHFP",
+ "TKEY",
+ "TLSA",
+ "TSIG",
+ "TXT",
+ "URI",
+ "X25",
+ "ZONEMD",
]
import dns.rdtypes.mxbase
import dns.immutable
+
@dns.immutable.immutable
class A(dns.rdata.Rdata):
# domain: the domain of the address
# address: the 16-bit address
- __slots__ = ['domain', 'address']
+ __slots__ = ["domain", "address"]
def __init__(self, rdclass, rdtype, domain, address):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
domain = self.domain.choose_relativity(origin, relativize)
- return '%s %o' % (domain, self.address)
+ return "%s %o" % (domain, self.address)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
domain = tok.get_name(origin, relativize, relativize_to)
address = tok.get_uint16(base=8)
return cls(rdclass, rdtype, domain, address)
"""Class CH rdata type classes."""
__all__ = [
- 'A',
+ "A",
]
"""A record."""
- __slots__ = ['address']
+ __slots__ = ["address"]
def __init__(self, rdclass, rdtype, address):
super().__init__(rdclass, rdtype)
return self.address
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_identifier()
return cls(rdclass, rdtype, address)
"""AAAA record."""
- __slots__ = ['address']
+ __slots__ = ["address"]
def __init__(self, rdclass, rdtype, address):
super().__init__(rdclass, rdtype)
return self.address
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_identifier()
return cls(rdclass, rdtype, address)
import dns.rdata
import dns.tokenizer
+
@dns.immutable.immutable
class APLItem:
"""An APL list item."""
- __slots__ = ['family', 'negation', 'address', 'prefix']
+ __slots__ = ["family", "negation", "address", "prefix"]
def __init__(self, family, negation, address, prefix):
self.family = dns.rdata.Rdata._as_uint16(family)
if address[i] != 0:
last = i + 1
break
- address = address[0: last]
+ address = address[0:last]
l = len(address)
assert l < 128
if self.negation:
l |= 0x80
- header = struct.pack('!HBB', self.family, self.prefix, l)
+ header = struct.pack("!HBB", self.family, self.prefix, l)
file.write(header)
file.write(address)
# see: RFC 3123
- __slots__ = ['items']
+ __slots__ = ["items"]
def __init__(self, rdclass, rdtype, items):
super().__init__(rdclass, rdtype)
for item in items:
if not isinstance(item, APLItem):
- raise ValueError('item not an APLItem')
+ raise ValueError("item not an APLItem")
self.items = tuple(items)
def to_text(self, origin=None, relativize=True, **kw):
- return ' '.join(map(str, self.items))
+ return " ".join(map(str, self.items))
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
items = []
for token in tok.get_remaining():
item = token.unescape().value
- if item[0] == '!':
+ if item[0] == "!":
negation = True
item = item[1:]
else:
negation = False
- (family, rest) = item.split(':', 1)
+ (family, rest) = item.split(":", 1)
family = int(family)
- (address, prefix) = rest.split('/', 1)
+ (address, prefix) = rest.split("/", 1)
prefix = int(prefix)
item = APLItem(family, negation, address, prefix)
items.append(item)
items = []
while parser.remaining() > 0:
- header = parser.get_struct('!HBB')
+ header = parser.get_struct("!HBB")
afdlen = header[2]
if afdlen > 127:
negation = True
l = len(address)
if header[0] == 1:
if l < 4:
- address += b'\x00' * (4 - l)
+ address += b"\x00" * (4 - l)
elif header[0] == 2:
if l < 16:
- address += b'\x00' * (16 - l)
+ address += b"\x00" * (16 - l)
else:
#
# This isn't really right according to the RFC, but it
# seems better than throwing an exception
#
- address = codecs.encode(address, 'hex_codec')
+ address = codecs.encode(address, "hex_codec")
item = APLItem(header[0], negation, address, header[1])
items.append(item)
return cls(rdclass, rdtype, items)
# see: RFC 4701
- __slots__ = ['data']
+ __slots__ = ["data"]
def __init__(self, rdclass, rdtype, data):
super().__init__(rdclass, rdtype)
return dns.rdata._base64ify(self.data, **kw)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
b64 = tok.concatenate_remaining_identifiers().encode()
data = base64.b64decode(b64)
return cls(rdclass, rdtype, data)
import dns.rdtypes.svcbbase
import dns.immutable
+
@dns.immutable.immutable
class HTTPS(dns.rdtypes.svcbbase.SVCBBase):
"""HTTPS record"""
class Gateway(dns.rdtypes.util.Gateway):
- name = 'IPSECKEY gateway'
+ name = "IPSECKEY gateway"
+
@dns.immutable.immutable
class IPSECKEY(dns.rdata.Rdata):
# see: RFC 4025
- __slots__ = ['precedence', 'gateway_type', 'algorithm', 'gateway', 'key']
+ __slots__ = ["precedence", "gateway_type", "algorithm", "gateway", "key"]
- def __init__(self, rdclass, rdtype, precedence, gateway_type, algorithm,
- gateway, key):
+ def __init__(
+ self, rdclass, rdtype, precedence, gateway_type, algorithm, gateway, key
+ ):
super().__init__(rdclass, rdtype)
gateway = Gateway(gateway_type, gateway)
self.precedence = self._as_uint8(precedence)
self.key = self._as_bytes(key)
def to_text(self, origin=None, relativize=True, **kw):
- gateway = Gateway(self.gateway_type, self.gateway).to_text(origin,
- relativize)
- return '%d %d %d %s %s' % (self.precedence, self.gateway_type,
- self.algorithm, gateway,
- dns.rdata._base64ify(self.key, **kw))
+ gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, relativize)
+ return "%d %d %d %s %s" % (
+ self.precedence,
+ self.gateway_type,
+ self.algorithm,
+ gateway,
+ dns.rdata._base64ify(self.key, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
precedence = tok.get_uint8()
gateway_type = tok.get_uint8()
algorithm = tok.get_uint8()
- gateway = Gateway.from_text(gateway_type, tok, origin, relativize,
- relativize_to)
+ gateway = Gateway.from_text(
+ gateway_type, tok, origin, relativize, relativize_to
+ )
b64 = tok.concatenate_remaining_identifiers().encode()
key = base64.b64decode(b64)
- return cls(rdclass, rdtype, precedence, gateway_type, algorithm,
- gateway.gateway, key)
+ return cls(
+ rdclass, rdtype, precedence, gateway_type, algorithm, gateway.gateway, key
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- header = struct.pack("!BBB", self.precedence, self.gateway_type,
- self.algorithm)
+ header = struct.pack("!BBB", self.precedence, self.gateway_type, self.algorithm)
file.write(header)
- Gateway(self.gateway_type, self.gateway).to_wire(file, compress,
- origin, canonicalize)
+ Gateway(self.gateway_type, self.gateway).to_wire(
+ file, compress, origin, canonicalize
+ )
file.write(self.key)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- header = parser.get_struct('!BBB')
+ header = parser.get_struct("!BBB")
gateway_type = header[1]
gateway = Gateway.from_wire_parser(gateway_type, parser, origin)
key = parser.get_remaining()
- return cls(rdclass, rdtype, header[0], gateway_type, header[2],
- gateway.gateway, key)
+ return cls(
+ rdclass, rdtype, header[0], gateway_type, header[2], gateway.gateway, key
+ )
def _write_string(file, s):
l = len(s)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(s)
# see: RFC 3403
- __slots__ = ['order', 'preference', 'flags', 'service', 'regexp',
- 'replacement']
+ __slots__ = ["order", "preference", "flags", "service", "regexp", "replacement"]
- def __init__(self, rdclass, rdtype, order, preference, flags, service,
- regexp, replacement):
+ def __init__(
+ self, rdclass, rdtype, order, preference, flags, service, regexp, replacement
+ ):
super().__init__(rdclass, rdtype)
self.flags = self._as_bytes(flags, True, 255)
self.service = self._as_bytes(service, True, 255)
def to_text(self, origin=None, relativize=True, **kw):
replacement = self.replacement.choose_relativity(origin, relativize)
- return '%d %d "%s" "%s" "%s" %s' % \
- (self.order, self.preference,
- dns.rdata._escapify(self.flags),
- dns.rdata._escapify(self.service),
- dns.rdata._escapify(self.regexp),
- replacement)
+ return '%d %d "%s" "%s" "%s" %s' % (
+ self.order,
+ self.preference,
+ dns.rdata._escapify(self.flags),
+ dns.rdata._escapify(self.service),
+ dns.rdata._escapify(self.regexp),
+ replacement,
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
order = tok.get_uint16()
preference = tok.get_uint16()
flags = tok.get_string()
service = tok.get_string()
regexp = tok.get_string()
replacement = tok.get_name(origin, relativize, relativize_to)
- return cls(rdclass, rdtype, order, preference, flags, service,
- regexp, replacement)
+ return cls(
+ rdclass, rdtype, order, preference, flags, service, regexp, replacement
+ )
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
two_ints = struct.pack("!HH", self.order, self.preference)
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (order, preference) = parser.get_struct('!HH')
+ (order, preference) = parser.get_struct("!HH")
strings = []
for _ in range(3):
s = parser.get_counted_bytes()
strings.append(s)
replacement = parser.get_name(origin)
- return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
- strings[2], replacement)
+ return cls(
+ rdclass,
+ rdtype,
+ order,
+ preference,
+ strings[0],
+ strings[1],
+ strings[2],
+ replacement,
+ )
def _processing_priority(self):
return (self.order, self.preference)
# see: RFC 1706
- __slots__ = ['address']
+ __slots__ = ["address"]
def __init__(self, rdclass, rdtype, address):
super().__init__(rdclass, rdtype)
return "0x%s" % binascii.hexlify(self.address).decode()
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_string()
- if address[0:2] != '0x':
- raise dns.exception.SyntaxError('string does not start with 0x')
- address = address[2:].replace('.', '')
+ 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')
+ raise dns.exception.SyntaxError("hexstring has odd length")
address = binascii.unhexlify(address.encode())
return cls(rdclass, rdtype, address)
# see: RFC 2163
- __slots__ = ['preference', 'map822', 'mapx400']
+ __slots__ = ["preference", "map822", "mapx400"]
def __init__(self, rdclass, rdtype, preference, map822, mapx400):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
map822 = self.map822.choose_relativity(origin, relativize)
mapx400 = self.mapx400.choose_relativity(origin, relativize)
- return '%d %s %s' % (self.preference, map822, mapx400)
+ return "%d %s %s" % (self.preference, map822, mapx400)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
map822 = tok.get_name(origin, relativize, relativize_to)
mapx400 = tok.get_name(origin, relativize, relativize_to)
# see: RFC 2782
- __slots__ = ['priority', 'weight', 'port', 'target']
+ __slots__ = ["priority", "weight", "port", "target"]
def __init__(self, rdclass, rdtype, priority, weight, port, target):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
target = self.target.choose_relativity(origin, relativize)
- return '%d %d %d %s' % (self.priority, self.weight, self.port,
- target)
+ return "%d %d %d %s" % (self.priority, self.weight, self.port, target)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
priority = tok.get_uint16()
weight = tok.get_uint16()
port = tok.get_uint16()
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- (priority, weight, port) = parser.get_struct('!HHH')
+ (priority, weight, port) = parser.get_struct("!HHH")
target = parser.get_name(origin)
return cls(rdclass, rdtype, priority, weight, port, target)
import dns.rdtypes.svcbbase
import dns.immutable
+
@dns.immutable.immutable
class SVCB(dns.rdtypes.svcbbase.SVCBBase):
"""SVCB record"""
import dns.rdata
try:
- _proto_tcp = socket.getprotobyname('tcp')
- _proto_udp = socket.getprotobyname('udp')
+ _proto_tcp = socket.getprotobyname("tcp")
+ _proto_udp = socket.getprotobyname("udp")
except OSError:
# Fall back to defaults in case /etc/protocols is unavailable.
_proto_tcp = 6
_proto_udp = 17
+
@dns.immutable.immutable
class WKS(dns.rdata.Rdata):
# see: RFC 1035
- __slots__ = ['address', 'protocol', 'bitmap']
+ __slots__ = ["address", "protocol", "bitmap"]
def __init__(self, rdclass, rdtype, address, protocol, bitmap):
super().__init__(rdclass, rdtype)
for j in range(0, 8):
if byte & (0x80 >> j):
bits.append(str(i * 8 + j))
- text = ' '.join(bits)
- return '%s %d %s' % (self.address, self.protocol, text)
+ text = " ".join(bits)
+ return "%s %d %s" % (self.address, self.protocol, text)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
address = tok.get_string()
protocol = tok.get_string()
if protocol.isdigit():
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
file.write(dns.ipv4.inet_aton(self.address))
- protocol = struct.pack('!B', self.protocol)
+ protocol = struct.pack("!B", self.protocol)
file.write(protocol)
file.write(self.bitmap)
"""Class IN rdata type classes."""
__all__ = [
- 'A',
- 'AAAA',
- 'APL',
- 'DHCID',
- 'HTTPS',
- 'IPSECKEY',
- 'KX',
- 'NAPTR',
- 'NSAP',
- 'NSAP_PTR',
- 'PX',
- 'SRV',
- 'SVCB',
- 'WKS',
+ "A",
+ "AAAA",
+ "APL",
+ "DHCID",
+ "HTTPS",
+ "IPSECKEY",
+ "KX",
+ "NAPTR",
+ "NSAP",
+ "NSAP_PTR",
+ "PX",
+ "SRV",
+ "SVCB",
+ "WKS",
]
"""DNS rdata type classes"""
__all__ = [
- 'ANY',
- 'IN',
- 'CH',
- 'dnskeybase',
- 'dsbase',
- 'euibase',
- 'mxbase',
- 'nsbase',
- 'svcbbase',
- 'tlsabase',
- 'txtbase',
- 'util'
+ "ANY",
+ "IN",
+ "CH",
+ "dnskeybase",
+ "dsbase",
+ "euibase",
+ "mxbase",
+ "nsbase",
+ "svcbbase",
+ "tlsabase",
+ "txtbase",
+ "util",
]
import dns.rdata
# wildcard import
-__all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822
+__all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822
+
class Flag(enum.IntFlag):
SEP = 0x0001
"""Base class for rdata that is like a DNSKEY record"""
- __slots__ = ['flags', 'protocol', 'algorithm', 'key']
+ __slots__ = ["flags", "protocol", "algorithm", "key"]
def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
super().__init__(rdclass, rdtype)
self.key = self._as_bytes(key)
def to_text(self, origin=None, relativize=True, **kw):
- return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
- dns.rdata._base64ify(self.key, **kw))
+ return "%d %d %d %s" % (
+ self.flags,
+ self.protocol,
+ self.algorithm,
+ dns.rdata._base64ify(self.key, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
flags = tok.get_uint16()
protocol = tok.get_uint8()
algorithm = tok.get_string()
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
- header = parser.get_struct('!HBB')
+ header = parser.get_struct("!HBB")
key = parser.get_remaining()
- return cls(rdclass, rdtype, header[0], header[1], header[2],
- key)
+ return cls(rdclass, rdtype, header[0], header[1], header[2], key)
+
### BEGIN generated Flag constants
"""Base class for rdata that is like a DS record"""
- __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest']
+ __slots__ = ["key_tag", "algorithm", "digest_type", "digest"]
- # Digest types registry: https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
+ # Digest types registry:
+ # https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
_digest_length_by_type = {
1: 20, # SHA-1, RFC 3658 Sec. 2.4
2: 32, # SHA-256, RFC 4509 Sec. 2.2
4: 48, # SHA-384, RFC 6605 Sec. 2
}
- def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type,
- digest):
+ def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, digest):
super().__init__(rdclass, rdtype)
self.key_tag = self._as_uint16(key_tag)
self.algorithm = dns.dnssectypes.Algorithm.make(algorithm)
self.digest = self._as_bytes(digest)
try:
if len(self.digest) != self._digest_length_by_type[self.digest_type]:
- raise ValueError('digest length inconsistent with digest type')
+ raise ValueError("digest length inconsistent with digest type")
except KeyError:
if self.digest_type == 0: # reserved, RFC 3658 Sec. 2.4
- raise ValueError('digest type 0 is reserved')
+ raise ValueError("digest type 0 is reserved")
def to_text(self, origin=None, relativize=True, **kw):
kw = kw.copy()
- chunksize = kw.pop('chunksize', 128)
- return '%d %d %d %s' % (self.key_tag, self.algorithm,
- self.digest_type,
- dns.rdata._hexify(self.digest,
- chunksize=chunksize,
- **kw))
+ chunksize = kw.pop("chunksize", 128)
+ return "%d %d %d %s" % (
+ self.key_tag,
+ self.algorithm,
+ self.digest_type,
+ dns.rdata._hexify(self.digest, chunksize=chunksize, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
key_tag = tok.get_uint16()
algorithm = tok.get_string()
digest_type = tok.get_uint8()
digest = tok.concatenate_remaining_identifiers().encode()
digest = binascii.unhexlify(digest)
- return cls(rdclass, rdtype, key_tag, algorithm, digest_type,
- digest)
+ return cls(rdclass, rdtype, key_tag, algorithm, digest_type, digest)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
- header = struct.pack("!HBB", self.key_tag, self.algorithm,
- self.digest_type)
+ header = struct.pack("!HBB", self.key_tag, self.algorithm, self.digest_type)
file.write(header)
file.write(self.digest)
# see: rfc7043.txt
- __slots__ = ['eui']
+ __slots__ = ["eui"]
# define these in subclasses
# byte_len = 6 # 0123456789ab (in hex)
# text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab
super().__init__(rdclass, rdtype)
self.eui = self._as_bytes(eui)
if len(self.eui) != self.byte_len:
- raise dns.exception.FormError('EUI%s rdata has to have %s bytes'
- % (self.byte_len * 8, self.byte_len))
+ raise dns.exception.FormError(
+ "EUI%s rdata has to have %s bytes" % (self.byte_len * 8, self.byte_len)
+ )
def to_text(self, origin=None, relativize=True, **kw):
- return dns.rdata._hexify(self.eui, chunksize=2, separator=b'-', **kw)
+ return dns.rdata._hexify(self.eui, chunksize=2, separator=b"-", **kw)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
text = tok.get_string()
if len(text) != cls.text_len:
raise dns.exception.SyntaxError(
- 'Input text must have %s characters' % cls.text_len)
+ "Input text must have %s characters" % cls.text_len
+ )
for i in range(2, cls.byte_len * 3 - 1, 3):
- if text[i] != '-':
- raise dns.exception.SyntaxError('Dash expected at position %s'
- % i)
- text = text.replace('-', '')
+ if text[i] != "-":
+ raise dns.exception.SyntaxError("Dash expected at position %s" % i)
+ text = text.replace("-", "")
try:
data = binascii.unhexlify(text.encode())
except (ValueError, TypeError) as ex:
- raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex))
+ raise dns.exception.SyntaxError("Hex decoding error: %s" % str(ex))
return cls(rdclass, rdtype, data)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
"""Base class for rdata that is like an MX record."""
- __slots__ = ['preference', 'exchange']
+ __slots__ = ["preference", "exchange"]
def __init__(self, rdclass, rdtype, preference, exchange):
super().__init__(rdclass, rdtype)
def to_text(self, origin=None, relativize=True, **kw):
exchange = self.exchange.choose_relativity(origin, relativize)
- return '%d %s' % (self.preference, exchange)
+ return "%d %s" % (self.preference, exchange)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
preference = tok.get_uint16()
exchange = tok.get_name(origin, relativize, relativize_to)
return cls(rdclass, rdtype, preference, exchange)
"""Base class for rdata that is like an NS record."""
- __slots__ = ['target']
+ __slots__ = ["target"]
def __init__(self, rdclass, rdtype, target):
super().__init__(rdclass, rdtype)
return str(target)
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
target = tok.get_name(origin, relativize, relativize_to)
return cls(rdclass, rdtype, target)
if isinstance(key, bytes):
# We decode to latin-1 so we get 0-255 as valid and do NOT interpret
# UTF-8 sequences
- key = key.decode('latin-1')
+ key = key.decode("latin-1")
if isinstance(key, str):
- if key.lower().startswith('key'):
+ if key.lower().startswith("key"):
force_generic = True
- if key[3:].startswith('0') and len(key) != 4:
+ if key[3:].startswith("0") and len(key) != 4:
# key has leading zeros
- raise ValueError('leading zeros in key')
- key = key.replace('-', '_')
+ raise ValueError("leading zeros in key")
+ key = key.replace("-", "_")
return (ParamKey.make(key), force_generic)
+
def key_to_text(key):
- return ParamKey.to_text(key).replace('_', '-').lower()
+ return ParamKey.to_text(key).replace("_", "-").lower()
+
# Like rdata escapify, but escapes ',' too.
_escaped = b'",\\'
+
def _escapify(qstring):
- text = ''
+ text = ""
for c in qstring:
if c in _escaped:
- text += '\\' + chr(c)
+ text += "\\" + chr(c)
elif c >= 0x20 and c < 0x7F:
text += chr(c)
else:
- text += '\\%03d' % c
+ text += "\\%03d" % c
return text
+
def _unescape(value):
- if value == '':
+ if value == "":
return value
- unescaped = b''
+ unescaped = b""
l = len(value)
i = 0
while i < l:
c = value[i]
i += 1
- if c == '\\':
+ if c == "\\":
if i >= l: # pragma: no cover (can't happen via tokenizer get())
raise dns.exception.UnexpectedEnd
c = value[i]
codepoint = int(c) * 100 + int(c2) * 10 + int(c3)
if codepoint > 255:
raise dns.exception.SyntaxError
- unescaped += b'%c' % (codepoint)
+ unescaped += b"%c" % (codepoint)
continue
unescaped += c.encode()
return unescaped
l = len(value)
i = 0
items = []
- unescaped = b''
+ unescaped = b""
while i < l:
c = value[i]
i += 1
- if c == ord('\\'):
+ if c == ord("\\"):
if i >= l: # pragma: no cover (can't happen via tokenizer get())
raise dns.exception.UnexpectedEnd
c = value[i]
i += 1
- unescaped += b'%c' % (c)
- elif c == ord(','):
+ unescaped += b"%c" % (c)
+ elif c == ord(","):
items.append(unescaped)
- unescaped = b''
+ unescaped = b""
else:
- unescaped += b'%c' % (c)
+ unescaped += b"%c" % (c)
items.append(unescaped)
return items
@dns.immutable.immutable
class GenericParam(Param):
- """Generic SVCB parameter
- """
+ """Generic SVCB parameter"""
+
def __init__(self, value):
self.value = dns.rdata.Rdata._as_bytes(value, True)
prior_k = None
for k in keys:
if k == prior_k:
- raise ValueError(f'duplicate key {k:d}')
+ raise ValueError(f"duplicate key {k:d}")
prior_k = k
if k == ParamKey.MANDATORY:
- raise ValueError('listed the mandatory key as mandatory')
+ raise ValueError("listed the mandatory key as mandatory")
self.keys = tuple(keys)
@classmethod
def from_value(cls, value):
- keys = [k.encode() for k in value.split(',')]
+ keys = [k.encode() for k in value.split(",")]
return cls(keys)
def to_text(self):
- return '"' + ','.join([key_to_text(key) for key in self.keys]) + '"'
+ return '"' + ",".join([key_to_text(key) for key in self.keys]) + '"'
@classmethod
def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613
while parser.remaining() > 0:
key = parser.get_uint16()
if key < last_key:
- raise dns.exception.FormError('manadatory keys not ascending')
+ raise dns.exception.FormError("manadatory keys not ascending")
last_key = key
keys.append(key)
return cls(keys)
def to_wire(self, file, origin=None): # pylint: disable=W0613
for key in self.keys:
- file.write(struct.pack('!H', key))
+ file.write(struct.pack("!H", key))
@dns.immutable.immutable
class ALPNParam(Param):
def __init__(self, ids):
self.ids = dns.rdata.Rdata._as_tuple(
- ids, lambda x: dns.rdata.Rdata._as_bytes(x, True, 255, False))
+ ids, lambda x: dns.rdata.Rdata._as_bytes(x, True, 255, False)
+ )
@classmethod
def from_value(cls, value):
return cls(_split(_unescape(value)))
def to_text(self):
- value = ','.join([_escapify(id) for id in self.ids])
+ value = ",".join([_escapify(id) for id in self.ids])
return '"' + dns.rdata._escapify(value.encode()) + '"'
@classmethod
def to_wire(self, file, origin=None): # pylint: disable=W0613
for id in self.ids:
- file.write(struct.pack('!B', len(id)))
+ file.write(struct.pack("!B", len(id)))
file.write(id)
@classmethod
def from_value(cls, value):
- if value is None or value == '':
+ if value is None or value == "":
return None
else:
- raise ValueError('no-default-alpn with non-empty value')
+ raise ValueError("no-default-alpn with non-empty value")
def to_text(self):
raise NotImplementedError # pragma: no cover
return cls(port)
def to_wire(self, file, origin=None): # pylint: disable=W0613
- file.write(struct.pack('!H', self.port))
+ file.write(struct.pack("!H", self.port))
@dns.immutable.immutable
class IPv4HintParam(Param):
def __init__(self, addresses):
self.addresses = dns.rdata.Rdata._as_tuple(
- addresses, dns.rdata.Rdata._as_ipv4_address)
+ addresses, dns.rdata.Rdata._as_ipv4_address
+ )
@classmethod
def from_value(cls, value):
- addresses = value.split(',')
+ addresses = value.split(",")
return cls(addresses)
def to_text(self):
- return '"' + ','.join(self.addresses) + '"'
+ return '"' + ",".join(self.addresses) + '"'
@classmethod
def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613
class IPv6HintParam(Param):
def __init__(self, addresses):
self.addresses = dns.rdata.Rdata._as_tuple(
- addresses, dns.rdata.Rdata._as_ipv6_address)
+ addresses, dns.rdata.Rdata._as_ipv6_address
+ )
@classmethod
def from_value(cls, value):
- addresses = value.split(',')
+ addresses = value.split(",")
return cls(addresses)
def to_text(self):
- return '"' + ','.join(self.addresses) + '"'
+ return '"' + ",".join(self.addresses) + '"'
@classmethod
def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613
@classmethod
def from_value(cls, value):
- if '\\' in value:
- raise ValueError('escape in ECH value')
+ if "\\" in value:
+ raise ValueError("escape in ECH value")
value = base64.b64decode(value.encode())
return cls(value)
def to_text(self):
- b64 = base64.b64encode(self.ech).decode('ascii')
+ b64 = base64.b64encode(self.ech).decode("ascii")
return f'"{b64}"'
@classmethod
emptiness = cls.emptiness()
if value is None:
if emptiness == Emptiness.NEVER:
- raise SyntaxError('value cannot be empty')
+ raise SyntaxError("value cannot be empty")
value = cls.from_value(value)
else:
if force_generic:
# see: draft-ietf-dnsop-svcb-https-01
- __slots__ = ['priority', 'target', 'params']
+ __slots__ = ["priority", "target", "params"]
def __init__(self, rdclass, rdtype, priority, target, params):
super().__init__(rdclass, rdtype)
# Note we have to say "not in" as we have None as a value
# so a get() and a not None test would be wrong.
if key not in params:
- raise ValueError(f'key {key:d} declared mandatory but not '
- 'present')
+ raise ValueError(
+ f"key {key:d} declared mandatory but not " "present"
+ )
# The no-default-alpn parameter requires the alpn parameter.
if ParamKey.NO_DEFAULT_ALPN in params:
if ParamKey.ALPN not in params:
- raise ValueError('no-default-alpn present, but alpn missing')
+ raise ValueError("no-default-alpn present, but alpn missing")
def to_text(self, origin=None, relativize=True, **kw):
target = self.target.choose_relativity(origin, relativize)
if value is None:
params.append(key_to_text(key))
else:
- kv = key_to_text(key) + '=' + value.to_text()
+ kv = key_to_text(key) + "=" + value.to_text()
params.append(kv)
if len(params) > 0:
- space = ' '
+ space = " "
else:
- space = ''
- return '%d %s%s%s' % (self.priority, target, space, ' '.join(params))
+ space = ""
+ return "%d %s%s%s" % (self.priority, target, space, " ".join(params))
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
priority = tok.get_uint16()
target = tok.get_name(origin, relativize, relativize_to)
if priority == 0:
token = tok.get()
if not token.is_eol_or_eof():
- raise SyntaxError('parameters in AliasMode')
+ raise SyntaxError("parameters in AliasMode")
tok.unget(token)
params = {}
while True:
tok.unget(token)
break
if token.ttype != dns.tokenizer.IDENTIFIER:
- raise SyntaxError('parameter is not an identifier')
- equals = token.value.find('=')
+ raise SyntaxError("parameter is not an identifier")
+ equals = token.value.find("=")
if equals == len(token.value) - 1:
# 'key=', so next token should be a quoted string without
# any intervening whitespace.
key = token.value[:-1]
token = tok.get(want_leading=True)
if token.ttype != dns.tokenizer.QUOTED_STRING:
- raise SyntaxError('whitespace after =')
+ raise SyntaxError("whitespace after =")
value = token.value
elif equals > 0:
# key=value
key = token.value[:equals]
- value = token.value[equals + 1:]
+ value = token.value[equals + 1 :]
elif equals == 0:
# =key
raise SyntaxError('parameter cannot start with "="')
priority = parser.get_uint16()
target = parser.get_name(origin)
if priority == 0 and parser.remaining() != 0:
- raise dns.exception.FormError('parameters in AliasMode')
+ raise dns.exception.FormError("parameters in AliasMode")
params = {}
prior_key = -1
while parser.remaining() > 0:
key = parser.get_uint16()
if key < prior_key:
- raise dns.exception.FormError('keys not in order')
+ raise dns.exception.FormError("keys not in order")
prior_key = key
vlen = parser.get_uint16()
pcls = _class_for_key.get(key, GenericParam)
# see: RFC 6698
- __slots__ = ['usage', 'selector', 'mtype', 'cert']
+ __slots__ = ["usage", "selector", "mtype", "cert"]
- def __init__(self, rdclass, rdtype, usage, selector,
- mtype, cert):
+ def __init__(self, rdclass, rdtype, usage, selector, mtype, cert):
super().__init__(rdclass, rdtype)
self.usage = self._as_uint8(usage)
self.selector = self._as_uint8(selector)
def to_text(self, origin=None, relativize=True, **kw):
kw = kw.copy()
- chunksize = kw.pop('chunksize', 128)
- return '%d %d %d %s' % (self.usage,
- self.selector,
- self.mtype,
- dns.rdata._hexify(self.cert,
- chunksize=chunksize,
- **kw))
+ chunksize = kw.pop("chunksize", 128)
+ return "%d %d %d %s" % (
+ self.usage,
+ self.selector,
+ self.mtype,
+ dns.rdata._hexify(self.cert, chunksize=chunksize, **kw),
+ )
@classmethod
- def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None
+ ):
usage = tok.get_uint8()
selector = tok.get_uint8()
mtype = tok.get_uint8()
"""Base class for rdata that is like a TXT record (see RFC 1035)."""
- __slots__ = ['strings']
-
- def __init__(self, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- strings: Iterable[Union[bytes, str]]):
+ __slots__ = ["strings"]
+
+ def __init__(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ strings: Iterable[Union[bytes, str]],
+ ):
"""Initialize a TXT-like rdata.
*rdclass*, an ``int`` is the rdataclass of the Rdata.
*strings*, a tuple of ``bytes``
"""
super().__init__(rdclass, rdtype)
- self.strings: Tuple[bytes] = self._as_tuple(strings, lambda x: self._as_bytes(x, True, 255))
-
- def to_text(self, origin: Optional[dns.name.Name]=None, relativize: bool=True, **kw: Dict[str, Any]) -> str:
- txt = ''
- prefix = ''
+ self.strings: Tuple[bytes] = self._as_tuple(
+ strings, lambda x: self._as_bytes(x, True, 255)
+ )
+
+ def to_text(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ **kw: Dict[str, Any]
+ ) -> str:
+ txt = ""
+ prefix = ""
for s in self.strings:
txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s))
- prefix = ' '
+ prefix = " "
return txt
@classmethod
- def from_text(cls, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- tok: dns.tokenizer.Tokenizer, origin: Optional[dns.name.Name]=None,
- relativize: bool=True, relativize_to: Optional[dns.name.Name]=None) -> dns.rdata.Rdata:
+ def from_text(
+ cls,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ tok: dns.tokenizer.Tokenizer,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+ ) -> dns.rdata.Rdata:
strings = []
for token in tok.get_remaining():
token = token.unescape_to_bytes()
# The 'if' below is always true in the current code, but we
# are leaving this check in in case things change some day.
- if not (token.is_quoted_string() or
- token.is_identifier()): # pragma: no cover
+ if not (
+ token.is_quoted_string() or token.is_identifier()
+ ): # pragma: no cover
raise dns.exception.SyntaxError("expected a string")
if len(token.value) > 255:
raise dns.exception.SyntaxError("string too long")
for s in self.strings:
l = len(s)
assert l < 256
- file.write(struct.pack('!B', l))
+ file.write(struct.pack("!B", l))
file.write(s)
@classmethod
class Gateway:
"""A helper class for the IPSECKEY gateway and AMTRELAY relay fields"""
+
name = ""
def __init__(self, type, gateway=None):
raise ValueError(self._invalid_type(self.type)) # pragma: no cover
@classmethod
- def from_text(cls, gateway_type, tok, origin=None, relativize=True,
- relativize_to=None):
+ def from_text(
+ cls, gateway_type, tok, origin=None, relativize=True, relativize_to=None
+ ):
if gateway_type in (0, 1, 2):
gateway = tok.get_string()
elif gateway_type == 3:
gateway = tok.get_name(origin, relativize, relativize_to)
else:
raise dns.exception.SyntaxError(
- cls._invalid_type(gateway_type)) # pragma: no cover
+ cls._invalid_type(gateway_type)
+ ) # pragma: no cover
return cls(gateway_type, gateway)
# pylint: disable=unused-argument
self.gateway.to_wire(file, None, origin, False)
else:
raise ValueError(self._invalid_type(self.type)) # pragma: no cover
+
# pylint: enable=unused-argument
@classmethod
class Bitmap:
"""A helper class for the NSEC/NSEC3/CSYNC type bitmaps"""
+
type_name = ""
def __init__(self, windows=None):
if byte & (0x80 >> j):
rdtype = window * 256 + i * 8 + j
bits.append(dns.rdatatype.to_text(rdtype))
- text += (' ' + ' '.join(bits))
+ text += " " + " ".join(bits)
return text
@classmethod
window = 0
octets = 0
prior_rdtype = 0
- bitmap = bytearray(b'\0' * 32)
+ bitmap = bytearray(b"\0" * 32)
windows = []
for rdtype in rdtypes:
if rdtype == prior_rdtype:
if new_window != window:
if octets != 0:
windows.append((window, bytes(bitmap[0:octets])))
- bitmap = bytearray(b'\0' * 32)
+ bitmap = bytearray(b"\0" * 32)
window = new_window
offset = rdtype % 256
byte = offset // 8
def to_wire(self, file):
for (window, bitmap) in self.windows:
- file.write(struct.pack('!BB', window, len(bitmap)))
+ file.write(struct.pack("!BB", window, len(bitmap)))
file.write(bitmap)
@classmethod
by_priority[rdata._processing_priority()].append(rdata)
return by_priority
+
def priority_processing_order(iterable):
items = list(iterable)
if len(items) == 1:
ordered.extend(rdatas)
return ordered
+
_no_weight = 0.1
+
def weighted_processing_order(iterable):
items = list(iterable)
if len(items) == 1:
ordered = []
for k in sorted(by_priority.keys()):
rdatas = by_priority[k]
- total = sum(rdata._processing_weight() or _no_weight
- for rdata in rdatas)
+ total = sum(rdata._processing_weight() or _no_weight for rdata in rdatas)
while len(rdatas) > 1:
r = random.uniform(0, total)
for (n, rdata) in enumerate(rdatas):
ordered.append(rdatas[0])
return ordered
+
def parse_formatted_hex(formatted, num_chunks, chunk_size, separator):
if len(formatted) != num_chunks * (chunk_size + 1) - 1:
- raise ValueError('invalid formatted hex string')
- value = b''
+ raise ValueError("invalid formatted hex string")
+ value = b""
for _ in range(num_chunks):
chunk = formatted[0:chunk_size]
- value += int(chunk, 16).to_bytes(chunk_size // 2, 'big')
+ value += int(chunk, 16).to_bytes(chunk_size // 2, "big")
formatted = formatted[chunk_size:]
if len(formatted) > 0 and formatted[0] != separator:
- raise ValueError('invalid formatted hex string')
+ raise ValueError("invalid formatted hex string")
formatted = formatted[1:]
return value
self.compress = {}
self.section = QUESTION
self.counts = [0, 0, 0, 0]
- self.output.write(b'\x00' * 12)
- self.mac = ''
+ self.output.write(b"\x00" * 12)
+ self.mac = ""
def _rollback(self, where):
"""Truncate the output buffer at offset *where*, and remove any
self._set_section(section)
with self._track_size():
- n = rdataset.to_wire(name, self.output, self.compress, self.origin,
- **kw)
+ n = rdataset.to_wire(name, self.output, self.compress, self.origin, **kw)
self.counts[section] += n
def add_edns(self, edns, ednsflags, payload, options=None):
# make sure the EDNS version in ednsflags agrees with edns
ednsflags &= 0xFF00FFFF
- ednsflags |= (edns << 16)
+ ednsflags |= edns << 16
opt = dns.message.Message._make_opt(ednsflags, payload, options)
self.add_rrset(ADDITIONAL, opt)
- def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data,
- request_mac, algorithm=dns.tsig.default_algorithm):
+ def add_tsig(
+ self,
+ keyname,
+ secret,
+ fudge,
+ id,
+ tsig_error,
+ other_data,
+ request_mac,
+ algorithm=dns.tsig.default_algorithm,
+ ):
"""Add a TSIG signature to the message."""
s = self.output.getvalue()
key = secret
else:
key = dns.tsig.Key(keyname, secret, algorithm)
- tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge,
- b'', id, tsig_error, other_data)
- (tsig, _) = dns.tsig.sign(s, key, tsig[0], int(time.time()),
- request_mac)
+ tsig = dns.message.Message._make_tsig(
+ keyname, algorithm, 0, fudge, b"", id, tsig_error, other_data
+ )
+ (tsig, _) = dns.tsig.sign(s, key, tsig[0], int(time.time()), request_mac)
self._write_tsig(tsig, keyname)
- def add_multi_tsig(self, ctx, keyname, secret, fudge, id, tsig_error,
- other_data, request_mac,
- algorithm=dns.tsig.default_algorithm):
+ def add_multi_tsig(
+ self,
+ ctx,
+ keyname,
+ secret,
+ fudge,
+ id,
+ tsig_error,
+ other_data,
+ request_mac,
+ algorithm=dns.tsig.default_algorithm,
+ ):
"""Add a TSIG signature to the message. Unlike add_tsig(), this can be
used for a series of consecutive DNS envelopes, e.g. for a zone
transfer over TCP [RFC2845, 4.4].
key = secret
else:
key = dns.tsig.Key(keyname, secret, algorithm)
- tsig = dns.message.Message._make_tsig(keyname, algorithm, 0, fudge,
- b'', id, tsig_error, other_data)
- (tsig, ctx) = dns.tsig.sign(s, key, tsig[0], int(time.time()),
- request_mac, ctx, True)
+ tsig = dns.message.Message._make_tsig(
+ keyname, algorithm, 0, fudge, b"", id, tsig_error, other_data
+ )
+ (tsig, ctx) = dns.tsig.sign(
+ s, key, tsig[0], int(time.time()), request_mac, ctx, True
+ )
self._write_tsig(tsig, keyname)
return ctx
self._set_section(ADDITIONAL)
with self._track_size():
keyname.to_wire(self.output, self.compress, self.origin)
- self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG,
- dns.rdataclass.ANY, 0, 0))
+ self.output.write(
+ struct.pack("!HHIH", dns.rdatatype.TSIG, dns.rdataclass.ANY, 0, 0)
+ )
rdata_start = self.output.tell()
tsig.to_wire(self.output)
after = self.output.tell()
self.output.seek(rdata_start - 2)
- self.output.write(struct.pack('!H', after - rdata_start))
+ self.output.write(struct.pack("!H", after - rdata_start))
self.counts[ADDITIONAL] += 1
self.output.seek(10)
- self.output.write(struct.pack('!H', self.counts[ADDITIONAL]))
+ self.output.write(struct.pack("!H", self.counts[ADDITIONAL]))
self.output.seek(0, io.SEEK_END)
def write_header(self):
"""
self.output.seek(0)
- self.output.write(struct.pack('!HHHHHH', self.id, self.flags,
- self.counts[0], self.counts[1],
- self.counts[2], self.counts[3]))
+ self.output.write(
+ struct.pack(
+ "!HHHHHH",
+ self.id,
+ self.flags,
+ self.counts[0],
+ self.counts[1],
+ self.counts[2],
+ self.counts[3],
+ )
+ )
self.output.seek(0, io.SEEK_END)
def get_wire(self):
import time
import random
import warnings
+
try:
import threading as _threading
except ImportError: # pragma: no cover
- import dummy_threading as _threading # type: ignore
+ import dummy_threading as _threading # type: ignore
import dns.exception
import dns.edns
import dns.reversename
import dns.tsig
-if sys.platform == 'win32':
+if sys.platform == "win32":
import dns.win32util
+
class NXDOMAIN(dns.exception.DNSException):
"""The DNS query name does not exist."""
- supp_kwargs = {'qnames', 'responses'}
+
+ supp_kwargs = {"qnames", "responses"}
fmt = None # we have our own __str__ implementation
# pylint: disable=arguments-differ
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- def _check_kwargs(self, qnames,
- responses=None):
+ def _check_kwargs(self, qnames, responses=None):
if not isinstance(qnames, (list, tuple, set)):
raise AttributeError("qnames must be a list, tuple or set")
if len(qnames) == 0:
return kwargs
def __str__(self):
- if 'qnames' not in self.kwargs:
+ if "qnames" not in self.kwargs:
return super().__str__()
- qnames = self.kwargs['qnames']
+ qnames = self.kwargs["qnames"]
if len(qnames) > 1:
- msg = 'None of DNS query names exist'
+ msg = "None of DNS query names exist"
else:
- msg = 'The DNS query name does not exist'
- qnames = ', '.join(map(str, qnames))
+ msg = "The DNS query name does not exist"
+ qnames = ", ".join(map(str, qnames))
return "{}: {}".format(msg, qnames)
@property
def canonical_name(self):
"""Return the unresolved canonical name."""
- if 'qnames' not in self.kwargs:
+ if "qnames" not in self.kwargs:
raise TypeError("parametrized exception required")
- for qname in self.kwargs['qnames']:
- response = self.kwargs['responses'][qname]
+ for qname in self.kwargs["qnames"]:
+ response = self.kwargs["responses"][qname]
try:
cname = response.canonical_name()
if cname != qname:
# We can just eat this exception as it means there was
# something wrong with the response.
pass
- return self.kwargs['qnames'][0]
+ return self.kwargs["qnames"][0]
def __add__(self, e_nx):
"""Augment by results from another NXDOMAIN exception."""
- qnames0 = list(self.kwargs.get('qnames', []))
- responses0 = dict(self.kwargs.get('responses', {}))
- responses1 = e_nx.kwargs.get('responses', {})
- for qname1 in e_nx.kwargs.get('qnames', []):
+ qnames0 = list(self.kwargs.get("qnames", []))
+ responses0 = dict(self.kwargs.get("responses", {}))
+ responses1 = e_nx.kwargs.get("responses", {})
+ for qname1 in e_nx.kwargs.get("qnames", []):
if qname1 not in qnames0:
qnames0.append(qname1)
if qname1 in responses1:
Returns a list of ``dns.name.Name``.
"""
- return self.kwargs['qnames']
+ return self.kwargs["qnames"]
def responses(self):
"""A map from queried names to their NXDOMAIN responses.
Returns a dict mapping a ``dns.name.Name`` to a
``dns.message.Message``.
"""
- return self.kwargs['responses']
+ return self.kwargs["responses"]
def response(self, qname):
"""The response for query *qname*.
Returns a ``dns.message.Message``.
"""
- return self.kwargs['responses'][qname]
+ return self.kwargs["responses"][qname]
class YXDOMAIN(dns.exception.DNSException):
"""The DNS query name is too long after DNAME substitution."""
-ErrorTuple = Tuple[Optional[str], bool, int, Union[Exception, str], Optional[dns.message.Message]]
+ErrorTuple = Tuple[
+ Optional[str], bool, int, Union[Exception, str], Optional[dns.message.Message]
+]
def _errors_to_text(errors: List[ErrorTuple]) -> List[str]:
"""Turn a resolution errors trace into a list of text."""
texts = []
for err in errors:
- texts.append('Server {} {} port {} answered {}'.format(err[0],
- 'TCP' if err[1] else 'UDP', err[2], err[3]))
+ texts.append(
+ "Server {} {} port {} answered {}".format(
+ err[0], "TCP" if err[1] else "UDP", err[2], err[3]
+ )
+ )
return texts
msg = "The resolution lifetime expired."
fmt = "%s after {timeout:.3f} seconds: {errors}" % msg[:-1]
- supp_kwargs = {'timeout', 'errors'}
+ supp_kwargs = {"timeout", "errors"}
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _fmt_kwargs(self, **kwargs):
- srv_msgs = _errors_to_text(kwargs['errors'])
- return super()._fmt_kwargs(timeout=kwargs['timeout'],
- errors='; '.join(srv_msgs))
+ srv_msgs = _errors_to_text(kwargs["errors"])
+ return super()._fmt_kwargs(
+ timeout=kwargs["timeout"], errors="; ".join(srv_msgs)
+ )
# We added more detail to resolution timeouts, but they are still
class NoAnswer(dns.exception.DNSException):
"""The DNS response does not contain an answer to the question."""
- fmt = 'The DNS response does not contain an answer ' + \
- 'to the question: {query}'
- supp_kwargs = {'response'}
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ fmt = "The DNS response does not contain an answer " + "to the question: {query}"
+ supp_kwargs = {"response"}
+
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _fmt_kwargs(self, **kwargs):
- return super()._fmt_kwargs(query=kwargs['response'].question)
+ return super()._fmt_kwargs(query=kwargs["response"].question)
def response(self):
- return self.kwargs['response']
+ return self.kwargs["response"]
class NoNameservers(dns.exception.DNSException):
msg = "All nameservers failed to answer the query."
fmt = "%s {query}: {errors}" % msg[:-1]
- supp_kwargs = {'request', 'errors'}
+ supp_kwargs = {"request", "errors"}
- # We do this as otherwise mypy complains about unexpected keyword argument idna_exception
+ # We do this as otherwise mypy complains about unexpected keyword argument
+ # idna_exception
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _fmt_kwargs(self, **kwargs):
- srv_msgs = _errors_to_text(kwargs['errors'])
- return super()._fmt_kwargs(query=kwargs['request'].question,
- errors='; '.join(srv_msgs))
+ srv_msgs = _errors_to_text(kwargs["errors"])
+ return super()._fmt_kwargs(
+ query=kwargs["request"].question, errors="; ".join(srv_msgs)
+ )
class NotAbsolute(dns.exception.DNSException):
class NoMetaqueries(dns.exception.DNSException):
"""DNS metaqueries are not allowed."""
+
class NoResolverConfiguration(dns.exception.DNSException):
"""Resolver configuration could not be read or specified no nameservers."""
+
class Answer:
"""DNS stub resolver answer.
RRset's name might not be the query name.
"""
- def __init__(self, qname: dns.name.Name, rdtype: dns.rdatatype.RdataType,
- rdclass: dns.rdataclass.RdataClass, response: dns.message.QueryMessage,
- nameserver: Optional[str]=None, port: Optional[int]=None):
+ def __init__(
+ self,
+ qname: dns.name.Name,
+ rdtype: dns.rdatatype.RdataType,
+ rdclass: dns.rdataclass.RdataClass,
+ response: dns.message.QueryMessage,
+ nameserver: Optional[str] = None,
+ port: Optional[int] = None,
+ ):
self.qname = qname
self.rdtype = rdtype
self.rdclass = rdclass
self.expiration = time.time() + self.chaining_result.minimum_ttl
def __getattr__(self, attr): # pragma: no cover
- if attr == 'name':
+ if attr == "name":
return self.rrset.name
- elif attr == 'ttl':
+ elif attr == "ttl":
return self.rrset.ttl
- elif attr == 'covers':
+ elif attr == "covers":
return self.rrset.covers
- elif attr == 'rdclass':
+ elif attr == "rdclass":
return self.rrset.rdclass
- elif attr == 'rdtype':
+ elif attr == "rdtype":
return self.rrset.rdtype
else:
raise AttributeError(attr)
class CacheStatistics:
- """Cache Statistics
- """
+ """Cache Statistics"""
def __init__(self, hits=0, misses=0):
self.hits = hits
self.hits = 0
self.misses = 0
- def clone(self) -> 'CacheStatistics':
+ def clone(self) -> "CacheStatistics":
return CacheStatistics(self.hits, self.misses)
class Cache(CacheBase):
"""Simple thread-safe DNS answer cache."""
- def __init__(self, cleaning_interval: float=300.0):
+ def __init__(self, cleaning_interval: float = 300.0):
"""*cleaning_interval*, a ``float`` is the number of seconds between
periodic cleanings.
"""
Returns None if no answer is cached for the key.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
Returns a ``dns.resolver.Answer`` or ``None``.
"""
def put(self, key: CacheKey, value: Answer) -> None:
"""Associate key and value in the cache.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
*value*, a ``dns.resolver.Answer``, the answer.
"""
self._maybe_clean()
self.data[key] = value
- def flush(self, key: Optional[CacheKey]=None) -> None:
+ def flush(self, key: Optional[CacheKey] = None) -> None:
"""Flush the cache.
- If *key* is not ``None``, only that item is flushed. Otherwise
- the entire cache is flushed.
+ If *key* is not ``None``, only that item is flushed. Otherwise the entire cache
+ is flushed.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
"""
with self.lock:
for a new one.
"""
- def __init__(self, max_size: int=100000):
+ def __init__(self, max_size: int = 100000):
"""*max_size*, an ``int``, is the maximum number of nodes to cache;
it must be greater than 0.
"""
Returns None if no answer is cached for the key.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
Returns a ``dns.resolver.Answer`` or ``None``.
"""
def put(self, key: CacheKey, value: Answer) -> None:
"""Associate key and value in the cache.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
*value*, a ``dns.resolver.Answer``, the answer.
"""
node.link_after(self.sentinel)
self.data[key] = node
- def flush(self, key: Optional[CacheKey]=None) -> None:
+ def flush(self, key: Optional[CacheKey] = None) -> None:
"""Flush the cache.
- If *key* is not ``None``, only that item is flushed. Otherwise
- the entire cache is flushed.
+ If *key* is not ``None``, only that item is flushed. Otherwise the entire cache
+ is flushed.
- *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` tuple whose values are the
- query name, rdtype, and rdclass respectively.
+ *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)``
+ tuple whose values are the query name, rdtype, and rdclass respectively.
"""
with self.lock:
gnode = next
self.data = {}
+
class _Resolution:
"""Helper class for dns.resolver.Resolver.resolve().
resolver data structures directly.
"""
- def __init__(self, resolver: 'BaseResolver', qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- rdclass: Union[dns.rdataclass.RdataClass, str],
- tcp: bool, raise_on_no_answer: bool, search: Optional[bool]):
+ def __init__(
+ self,
+ resolver: "BaseResolver",
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ tcp: bool,
+ raise_on_no_answer: bool,
+ search: Optional[bool],
+ ):
if isinstance(qname, str):
qname = dns.name.from_text(qname, None)
the_rdtype = dns.rdatatype.RdataType.make(rdtype)
self.request: Optional[dns.message.QueryMessage] = None
self.backoff = 0.0
- def next_request(self) -> Tuple[Optional[dns.message.QueryMessage], Optional[Answer]]:
+ def next_request(
+ self,
+ ) -> Tuple[Optional[dns.message.QueryMessage], Optional[Answer]]:
"""Get the next request to send, and check the cache.
Returns a (request, answer) tuple. At most one of request or
# Do we know the answer?
if self.resolver.cache:
- answer = self.resolver.cache.get((self.qname, self.rdtype,
- self.rdclass))
+ answer = self.resolver.cache.get(
+ (self.qname, self.rdtype, self.rdclass)
+ )
if answer is not None:
if answer.rrset is None and self.raise_on_no_answer:
raise NoAnswer(response=answer.response)
else:
return (None, answer)
- answer = self.resolver.cache.get((self.qname,
- dns.rdatatype.ANY,
- self.rdclass))
- if answer is not None and \
- answer.response.rcode() == dns.rcode.NXDOMAIN:
+ answer = self.resolver.cache.get(
+ (self.qname, dns.rdatatype.ANY, self.rdclass)
+ )
+ if answer is not None and answer.response.rcode() == dns.rcode.NXDOMAIN:
# cached NXDOMAIN; record it and continue to next
# name.
self.nxdomain_responses[self.qname] = answer.response
continue
# Build the request
- request = dns.message.make_query(self.qname, self.rdtype,
- self.rdclass)
+ request = dns.message.make_query(self.qname, self.rdtype, self.rdclass)
if self.resolver.keyname is not None:
- request.use_tsig(self.resolver.keyring, self.resolver.keyname,
- algorithm=self.resolver.keyalgorithm)
- request.use_edns(self.resolver.edns, self.resolver.ednsflags,
- self.resolver.payload,
- options=self.resolver.ednsoptions)
+ request.use_tsig(
+ self.resolver.keyring,
+ self.resolver.keyname,
+ algorithm=self.resolver.keyalgorithm,
+ )
+ request.use_edns(
+ self.resolver.edns,
+ self.resolver.ednsflags,
+ self.resolver.payload,
+ options=self.resolver.ednsoptions,
+ )
if self.resolver.flags is not None:
request.flags = self.resolver.flags
# it's only NXDOMAINs as anything else would have returned
# before now.)
#
- raise NXDOMAIN(qnames=self.qnames_to_try,
- responses=self.nxdomain_responses)
+ raise NXDOMAIN(qnames=self.qnames_to_try, responses=self.nxdomain_responses)
def next_nameserver(self) -> Tuple[str, int, bool, float]:
if self.retry_with_tcp:
self.backoff = min(self.backoff * 2, 2)
self.nameserver = self.current_nameservers.pop(0)
- self.port = self.resolver.nameserver_ports.get(self.nameserver,
- self.resolver.port)
+ self.port = self.resolver.nameserver_ports.get(
+ self.nameserver, self.resolver.port
+ )
self.tcp_attempt = self.tcp
return (self.nameserver, self.port, self.tcp_attempt, backoff)
- def query_result(self, response: Optional[dns.message.Message],
- ex: Optional[Exception]) -> Tuple[Optional[Answer], bool]:
+ def query_result(
+ self, response: Optional[dns.message.Message], ex: Optional[Exception]
+ ) -> Tuple[Optional[Answer], bool]:
#
# returns an (answer: Answer, end_loop: bool) tuple.
#
if ex:
# Exception during I/O or from_wire()
assert response is None
- self.errors.append((self.nameserver, self.tcp_attempt, self.port,
- ex, response))
- if isinstance(ex, dns.exception.FormError) or \
- isinstance(ex, EOFError) or \
- isinstance(ex, OSError) or \
- isinstance(ex, NotImplementedError):
+ self.errors.append(
+ (self.nameserver, self.tcp_attempt, self.port, ex, response)
+ )
+ if (
+ isinstance(ex, dns.exception.FormError)
+ or isinstance(ex, EOFError)
+ or isinstance(ex, OSError)
+ or isinstance(ex, NotImplementedError)
+ ):
# This nameserver is no good, take it out of the mix.
self.nameservers.remove(self.nameserver)
elif isinstance(ex, dns.message.Truncated):
rcode = response.rcode()
if rcode == dns.rcode.NOERROR:
try:
- answer = Answer(self.qname, self.rdtype, self.rdclass, response,
- self.nameserver, self.port)
+ answer = Answer(
+ self.qname,
+ self.rdtype,
+ self.rdclass,
+ response,
+ self.nameserver,
+ self.port,
+ )
except Exception as e:
- self.errors.append((self.nameserver, self.tcp_attempt,
- self.port, e, response))
+ self.errors.append(
+ (self.nameserver, self.tcp_attempt, self.port, e, response)
+ )
# The nameserver is no good, take it out of the mix.
self.nameservers.remove(self.nameserver)
return (None, False)
if self.resolver.cache:
- self.resolver.cache.put((self.qname, self.rdtype,
- self.rdclass), answer)
+ self.resolver.cache.put((self.qname, self.rdtype, self.rdclass), answer)
if answer.rrset is None and self.raise_on_no_answer:
raise NoAnswer(response=answer.response)
return (answer, True)
# Further validate the response by making an Answer, even
# if we aren't going to cache it.
try:
- answer = Answer(self.qname, dns.rdatatype.ANY,
- dns.rdataclass.IN, response)
+ answer = Answer(
+ self.qname, dns.rdatatype.ANY, dns.rdataclass.IN, response
+ )
except Exception as e:
- self.errors.append((self.nameserver, self.tcp_attempt,
- self.port, e, response))
+ self.errors.append(
+ (self.nameserver, self.tcp_attempt, self.port, e, response)
+ )
# The nameserver is no good, take it out of the mix.
self.nameservers.remove(self.nameserver)
return (None, False)
self.nxdomain_responses[self.qname] = response
if self.resolver.cache:
- self.resolver.cache.put((self.qname,
- dns.rdatatype.ANY,
- self.rdclass), answer)
+ self.resolver.cache.put(
+ (self.qname, dns.rdatatype.ANY, self.rdclass), answer
+ )
# Make next_nameserver() return None, so caller breaks its
# inner loop and calls next_request().
return (None, True)
elif rcode == dns.rcode.YXDOMAIN:
yex = YXDOMAIN()
- self.errors.append((self.nameserver, self.tcp_attempt,
- self.port, yex, response))
+ self.errors.append(
+ (self.nameserver, self.tcp_attempt, self.port, yex, response)
+ )
raise yex
else:
#
#
if rcode != dns.rcode.SERVFAIL or not self.resolver.retry_servfail:
self.nameservers.remove(self.nameserver)
- self.errors.append((self.nameserver, self.tcp_attempt, self.port,
- dns.rcode.to_text(rcode), response))
+ self.errors.append(
+ (
+ self.nameserver,
+ self.tcp_attempt,
+ self.port,
+ dns.rcode.to_text(rcode),
+ response,
+ )
+ )
return (None, False)
rotate: bool
ndots: Optional[int]
- def __init__(self, filename: str='/etc/resolv.conf', configure: bool=True):
+ def __init__(self, filename: str = "/etc/resolv.conf", configure: bool = True):
"""*filename*, a ``str`` or file object, specifying a file
in standard /etc/resolv.conf format. This parameter is meaningful
only when *configure* is true and the platform is POSIX.
self.reset()
if configure:
- if sys.platform == 'win32':
+ if sys.platform == "win32":
self.read_registry()
elif filename:
self.read_resolv_conf(filename)
f = stack.enter_context(open(f))
except OSError:
# /etc/resolv.conf doesn't exist, can't be read, etc.
- raise NoResolverConfiguration(f'cannot open {f}')
+ raise NoResolverConfiguration(f"cannot open {f}")
for l in f:
- if len(l) == 0 or l[0] == '#' or l[0] == ';':
+ if len(l) == 0 or l[0] == "#" or l[0] == ";":
continue
tokens = l.split()
if len(tokens) < 2:
continue
- if tokens[0] == 'nameserver':
+ if tokens[0] == "nameserver":
self.nameservers.append(tokens[1])
- elif tokens[0] == 'domain':
+ elif tokens[0] == "domain":
self.domain = dns.name.from_text(tokens[1])
# domain and search are exclusive
self.search = []
- elif tokens[0] == 'search':
+ elif tokens[0] == "search":
# the last search wins
self.search = []
for suffix in tokens[1:]:
self.search.append(dns.name.from_text(suffix))
# We don't set domain as it is not used if
# len(self.search) > 0
- elif tokens[0] == 'options':
+ elif tokens[0] == "options":
for opt in tokens[1:]:
- if opt == 'rotate':
+ if opt == "rotate":
self.rotate = True
- elif opt == 'edns0':
+ elif opt == "edns0":
self.use_edns()
- elif 'timeout' in opt:
+ elif "timeout" in opt:
try:
- self.timeout = int(opt.split(':')[1])
+ self.timeout = int(opt.split(":")[1])
except (ValueError, IndexError):
pass
- elif 'ndots' in opt:
+ elif "ndots" in opt:
try:
- self.ndots = int(opt.split(':')[1])
+ self.ndots = int(opt.split(":")[1])
except (ValueError, IndexError):
pass
if len(self.nameservers) == 0:
- raise NoResolverConfiguration('no nameservers')
+ raise NoResolverConfiguration("no nameservers")
def read_registry(self) -> None:
"""Extract resolver configuration from the Windows registry."""
except AttributeError:
raise NotImplementedError
- def _compute_timeout(self, start: float, lifetime: Optional[float]=None,
- errors: Optional[List[ErrorTuple]]=None) -> float:
+ def _compute_timeout(
+ self,
+ start: float,
+ lifetime: Optional[float] = None,
+ errors: Optional[List[ErrorTuple]] = None,
+ ) -> float:
lifetime = self.lifetime if lifetime is None else lifetime
now = time.time()
duration = now - start
raise LifetimeTimeout(timeout=duration, errors=errors)
return min(lifetime - duration, self.timeout)
- def _get_qnames_to_try(self, qname: dns.name.Name, search: Optional[bool]) -> List[dns.name.Name]:
+ def _get_qnames_to_try(
+ self, qname: dns.name.Name, search: Optional[bool]
+ ) -> List[dns.name.Name]:
# This is a separate method so we can unit test the search
# rules without requiring the Internet.
if search is None:
qnames_to_try.append(abs_qname)
return qnames_to_try
- def use_tsig(self, keyring: Any, keyname: Optional[Union[dns.name.Name, str]]=None,
- algorithm: Union[dns.name.Name, str]=dns.tsig.default_algorithm) -> None:
+ def use_tsig(
+ self,
+ keyring: Any,
+ keyname: Optional[Union[dns.name.Name, str]] = None,
+ algorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm,
+ ) -> None:
"""Add a TSIG signature to each query.
The parameters are passed to ``dns.message.Message.use_tsig()``;
self.keyname = keyname
self.keyalgorithm = algorithm
- def use_edns(self, edns: Optional[Union[int, bool]]=0, ednsflags: int=0,
- payload: int=dns.message.DEFAULT_EDNS_PAYLOAD,
- options: Optional[List[dns.edns.Option]]=None) -> None:
+ def use_edns(
+ self,
+ edns: Optional[Union[int, bool]] = 0,
+ ednsflags: int = 0,
+ payload: int = dns.message.DEFAULT_EDNS_PAYLOAD,
+ options: Optional[List[dns.edns.Option]] = None,
+ ) -> None:
"""Configure EDNS behavior.
*edns*, an ``int``, is the EDNS level to use. Specifying
for nameserver in nameservers:
if not dns.inet.is_address(nameserver):
try:
- if urlparse(nameserver).scheme != 'https':
+ if urlparse(nameserver).scheme != "https":
raise NotImplementedError
except Exception:
- raise ValueError(f'nameserver {nameserver} is not an '
- 'IP address or valid https URL')
+ raise ValueError(
+ f"nameserver {nameserver} is not an "
+ "IP address or valid https URL"
+ )
self._nameservers = nameservers
else:
- raise ValueError('nameservers must be a list'
- ' (not a {})'.format(type(nameservers)))
+ raise ValueError(
+ "nameservers must be a list" " (not a {})".format(type(nameservers))
+ )
class Resolver(BaseResolver):
"""DNS stub resolver."""
- def resolve(self, qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
- tcp: bool = False, source: Optional[str] = None,
- raise_on_no_answer: bool = True, source_port: int = 0,
- lifetime: Optional[float] = None,
- search: Optional[bool] = None) -> Answer: # pylint: disable=arguments-differ
+ def resolve(
+ self,
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+ search: Optional[bool] = None,
+ ) -> Answer: # pylint: disable=arguments-differ
"""Query nameservers to find the answer to the question.
The *qname*, *rdtype*, and *rdclass* parameters may be objects
"""
- resolution = _Resolution(self, qname, rdtype, rdclass, tcp,
- raise_on_no_answer, search)
+ resolution = _Resolution(
+ self, qname, rdtype, rdclass, tcp, raise_on_no_answer, search
+ )
start = time.time()
while True:
(request, answer) = resolution.next_request()
(nameserver, port, tcp, backoff) = resolution.next_nameserver()
if backoff:
time.sleep(backoff)
- timeout = self._compute_timeout(start, lifetime,
- resolution.errors)
+ timeout = self._compute_timeout(start, lifetime, resolution.errors)
try:
if dns.inet.is_address(nameserver):
if tcp:
- response = dns.query.tcp(request, nameserver,
- timeout=timeout,
- port=port,
- source=source,
- source_port=source_port)
+ response = dns.query.tcp(
+ request,
+ nameserver,
+ timeout=timeout,
+ port=port,
+ source=source,
+ source_port=source_port,
+ )
else:
- response = dns.query.udp(request,
- nameserver,
- timeout=timeout,
- port=port,
- source=source,
- source_port=source_port,
- raise_on_truncation=True)
+ response = dns.query.udp(
+ request,
+ nameserver,
+ timeout=timeout,
+ port=port,
+ source=source,
+ source_port=source_port,
+ raise_on_truncation=True,
+ )
else:
- response = dns.query.https(request, nameserver,
- timeout=timeout)
+ response = dns.query.https(request, nameserver, timeout=timeout)
except Exception as ex:
(_, done) = resolution.query_result(None, ex)
continue
if answer is not None:
return answer
- def query(self, qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- tcp: bool=False, source: Optional[str]=None, raise_on_no_answer: bool=True, source_port: int=0,
- lifetime: Optional[float]=None) -> Answer: # pragma: no cover
+ def query(
+ self,
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+ ) -> Answer: # pragma: no cover
"""Query nameservers to find the answer to the question.
This method calls resolve() with ``search=True``, and is
dnspython. See the documentation for the resolve() method for
further details.
"""
- warnings.warn('please use dns.resolver.Resolver.resolve() instead',
- DeprecationWarning, stacklevel=2)
- return self.resolve(qname, rdtype, rdclass, tcp, source,
- raise_on_no_answer, source_port, lifetime,
- True)
-
- def resolve_address(self, ipaddr: str, *args: Any, **kwargs: Dict[str, Any]) -> Answer:
+ warnings.warn(
+ "please use dns.resolver.Resolver.resolve() instead",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return self.resolve(
+ qname,
+ rdtype,
+ rdclass,
+ tcp,
+ source,
+ raise_on_no_answer,
+ source_port,
+ lifetime,
+ True,
+ )
+
+ def resolve_address(
+ self, ipaddr: str, *args: Any, **kwargs: Dict[str, Any]
+ ) -> Answer:
"""Use a resolver to run a reverse query for PTR records.
This utilizes the resolve() method to perform a PTR lookup on the
# in the kwargs more than once.
modified_kwargs: Dict[str, Any] = {}
modified_kwargs.update(kwargs)
- modified_kwargs['rdtype'] = dns.rdatatype.PTR
- modified_kwargs['rdclass'] = dns.rdataclass.IN
- return self.resolve(dns.reversename.from_address(ipaddr),
- *args, **modified_kwargs) # type: ignore[arg-type]
+ modified_kwargs["rdtype"] = dns.rdatatype.PTR
+ modified_kwargs["rdclass"] = dns.rdataclass.IN
+ return self.resolve(
+ dns.reversename.from_address(ipaddr), *args, **modified_kwargs
+ ) # type: ignore[arg-type]
# pylint: disable=redefined-outer-name
default_resolver = Resolver()
-def resolve(qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- tcp: bool=False, source: Optional[str]=None, raise_on_no_answer: bool=True, source_port: int=0,
- lifetime: Optional[float]=None, search: Optional[bool]=None) -> Answer: # pragma: no cover
+def resolve(
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+ search: Optional[bool] = None,
+) -> Answer: # pragma: no cover
"""Query nameservers to find the answer to the question.
parameters.
"""
- return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source,
- raise_on_no_answer, source_port,
- lifetime, search)
-
-def query(qname: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.A,
- rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- tcp: bool=False, source: Optional[str]=None, raise_on_no_answer: bool=True, source_port: int=0,
- lifetime: Optional[float]=None) -> Answer: # pragma: no cover
+ return get_default_resolver().resolve(
+ qname,
+ rdtype,
+ rdclass,
+ tcp,
+ source,
+ raise_on_no_answer,
+ source_port,
+ lifetime,
+ search,
+ )
+
+
+def query(
+ qname: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A,
+ rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ tcp: bool = False,
+ source: Optional[str] = None,
+ raise_on_no_answer: bool = True,
+ source_port: int = 0,
+ lifetime: Optional[float] = None,
+) -> Answer: # pragma: no cover
"""Query nameservers to find the answer to the question.
This method calls resolve() with ``search=True``, and is
dnspython. See the documentation for the resolve() method for
further details.
"""
- warnings.warn('please use dns.resolver.resolve() instead',
- DeprecationWarning, stacklevel=2)
- return resolve(qname, rdtype, rdclass, tcp, source,
- raise_on_no_answer, source_port, lifetime,
- True)
+ warnings.warn(
+ "please use dns.resolver.resolve() instead", DeprecationWarning, stacklevel=2
+ )
+ return resolve(
+ qname,
+ rdtype,
+ rdclass,
+ tcp,
+ source,
+ raise_on_no_answer,
+ source_port,
+ lifetime,
+ True,
+ )
def resolve_address(ipaddr: str, *args: Any, **kwargs: Dict[str, Any]) -> Answer:
return get_default_resolver().canonical_name(name)
-def zone_for_name(name: Union[dns.name.Name, str], rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN,
- tcp: bool=False, resolver: Optional[Resolver]=None,
- lifetime: Optional[float]=None) -> dns.name.Name:
+def zone_for_name(
+ name: Union[dns.name.Name, str],
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ tcp: bool = False,
+ resolver: Optional[Resolver] = None,
+ lifetime: Optional[float] = None,
+) -> dns.name.Name:
"""Find the name of the zone which contains the specified name.
*name*, an absolute ``dns.name.Name`` or ``str``, the query name.
rlifetime = 0
else:
rlifetime = None
- answer = resolver.resolve(name, dns.rdatatype.SOA, rdclass, tcp,
- lifetime=rlifetime)
+ answer = resolver.resolve(
+ name, dns.rdatatype.SOA, rdclass, tcp, lifetime=rlifetime
+ )
assert answer.rrset is not None
if answer.rrset.name == name:
return name
except dns.name.NoParent:
raise NoRootSOA
+
#
# Support for overriding the system resolver for all python code in the
# running process.
_original_gethostbyaddr = socket.gethostbyaddr
-def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
- proto=0, flags=0):
+def _getaddrinfo(
+ host=None, service=None, family=socket.AF_UNSPEC, socktype=0, proto=0, flags=0
+):
if flags & socket.AI_NUMERICHOST != 0:
# Short circuit directly into the system's getaddrinfo(). We're
# not adding any value in this case, and this avoids infinite loops
# because dns.query.* needs to call getaddrinfo() for IPv6 scoping
# reasons. We will also do this short circuit below if we
# discover that the host is an address literal.
- return _original_getaddrinfo(host, service, family, socktype, proto,
- flags)
+ return _original_getaddrinfo(host, service, family, socktype, proto, flags)
if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0:
# Not implemented. We raise a gaierror as opposed to a
# NotImplementedError as it helps callers handle errors more
# no EAI_SYSTEM on Windows [Issue #416]. We didn't go for
# EAI_BADFLAGS as the flags aren't bad, we just don't
# implement them.
- raise socket.gaierror(socket.EAI_FAIL,
- 'Non-recoverable failure in name resolution')
+ raise socket.gaierror(
+ socket.EAI_FAIL, "Non-recoverable failure in name resolution"
+ )
if host is None and service is None:
- raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
v6addrs = []
v4addrs = []
canonical_name = None # pylint: disable=redefined-outer-name
# Is host None or an address literal? If so, use the system's
# getaddrinfo().
if host is None:
- return _original_getaddrinfo(host, service, family, socktype,
- proto, flags)
+ return _original_getaddrinfo(host, service, family, socktype, proto, flags)
try:
# We don't care about the result of af_for_address(), we're just
# calling it so it raises an exception if host is not an IPv4 or
# IPv6 address.
dns.inet.af_for_address(host)
- return _original_getaddrinfo(host, service, family, socktype,
- proto, flags)
+ return _original_getaddrinfo(host, service, family, socktype, proto, flags)
except Exception:
pass
# Something needs resolution!
try:
if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
- v6 = _resolver.resolve(host, dns.rdatatype.AAAA,
- raise_on_no_answer=False)
+ v6 = _resolver.resolve(host, dns.rdatatype.AAAA, raise_on_no_answer=False)
# Note that setting host ensures we query the same name
# for A as we did for AAAA. (This is just in case search lists
# are active by default in the resolver configuration and
for rdata in v6.rrset:
v6addrs.append(rdata.address)
if family == socket.AF_INET or family == socket.AF_UNSPEC:
- v4 = _resolver.resolve(host, dns.rdatatype.A,
- raise_on_no_answer=False)
+ v4 = _resolver.resolve(host, dns.rdatatype.A, raise_on_no_answer=False)
canonical_name = v4.canonical_name.to_text(True)
if v4.rrset is not None:
for rdata in v4.rrset:
v4addrs.append(rdata.address)
except dns.resolver.NXDOMAIN:
- raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
except Exception:
# We raise EAI_AGAIN here as the failure may be temporary
# (e.g. a timeout) and EAI_SYSTEM isn't defined on Windows.
# [Issue #416]
- raise socket.gaierror(socket.EAI_AGAIN,
- 'Temporary failure in name resolution')
+ raise socket.gaierror(socket.EAI_AGAIN, "Temporary failure in name resolution")
port = None
try:
# Is it a port literal?
except Exception:
pass
if port is None:
- raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
tuples = []
if socktype == 0:
socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM]
if flags & socket.AI_CANONNAME != 0:
cname = canonical_name
else:
- cname = ''
+ cname = ""
if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
for addr in v6addrs:
for socktype in socktypes:
for proto in _protocols_for_socktype[socktype]:
- tuples.append((socket.AF_INET6, socktype, proto,
- cname, (addr, port, 0, 0)))
+ tuples.append(
+ (socket.AF_INET6, socktype, proto, cname, (addr, port, 0, 0))
+ )
if family == socket.AF_INET or family == socket.AF_UNSPEC:
for addr in v4addrs:
for socktype in socktypes:
for proto in _protocols_for_socktype[socktype]:
- tuples.append((socket.AF_INET, socktype, proto,
- cname, (addr, port)))
+ tuples.append(
+ (socket.AF_INET, socktype, proto, cname, (addr, port))
+ )
if len(tuples) == 0:
- raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
return tuples
else:
scope = None
family = socket.AF_INET
- tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM,
- socket.SOL_TCP, 0)
+ tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, socket.SOL_TCP, 0)
if len(tuples) > 1:
- raise socket.error('sockaddr resolved to multiple addresses')
+ raise socket.error("sockaddr resolved to multiple addresses")
addr = tuples[0][4][0]
if flags & socket.NI_DGRAM:
- pname = 'udp'
+ pname = "udp"
else:
- pname = 'tcp'
+ pname = "tcp"
qname = dns.reversename.from_address(addr)
if flags & socket.NI_NUMERICHOST == 0:
try:
- answer = _resolver.resolve(qname, 'PTR')
+ answer = _resolver.resolve(qname, "PTR")
hostname = answer.rrset[0].target.to_text(True)
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
if flags & socket.NI_NAMEREQD:
- raise socket.gaierror(socket.EAI_NONAME,
- 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
hostname = addr
if scope is not None:
- hostname += '%' + str(scope)
+ hostname += "%" + str(scope)
else:
hostname = addr
if scope is not None:
- hostname += '%' + str(scope)
+ hostname += "%" + str(scope)
if flags & socket.NI_NUMERICSERV:
service = str(port)
else:
def _gethostbyname_ex(name):
aliases = []
addresses = []
- tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
- socket.SOL_TCP, socket.AI_CANONNAME)
+ tuples = _getaddrinfo(
+ name, 0, socket.AF_INET, socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_CANONNAME
+ )
canonical = tuples[0][3]
for item in tuples:
addresses.append(item[4][0])
try:
dns.ipv4.inet_aton(ip)
except Exception:
- raise socket.gaierror(socket.EAI_NONAME,
- 'Name or service not known')
+ raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
sockaddr = (ip, 80)
family = socket.AF_INET
(name, _) = _getnameinfo(sockaddr, socket.NI_NAMEREQD)
aliases = []
addresses = []
- tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP,
- socket.AI_CANONNAME)
+ tuples = _getaddrinfo(
+ name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_CANONNAME
+ )
canonical = tuples[0][3]
# We only want to include an address from the tuples if it's the
# same as the one we asked about. We do this comparison in binary
return (canonical, aliases, addresses)
-def override_system_resolver(resolver: Optional[Resolver]=None) -> None:
+def override_system_resolver(resolver: Optional[Resolver] = None) -> None:
"""Override the system resolver routines in the socket module with
versions which use dnspython's resolver.
import dns.ipv6
import dns.ipv4
-ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.')
-ipv6_reverse_domain = dns.name.from_text('ip6.arpa.')
+ipv4_reverse_domain = dns.name.from_text("in-addr.arpa.")
+ipv6_reverse_domain = dns.name.from_text("ip6.arpa.")
-def from_address(text: str, v4_origin: dns.name.Name=ipv4_reverse_domain,
- v6_origin: dns.name.Name=ipv6_reverse_domain) -> dns.name.Name:
+def from_address(
+ text: str,
+ v4_origin: dns.name.Name = ipv4_reverse_domain,
+ v6_origin: dns.name.Name = ipv6_reverse_domain,
+) -> dns.name.Name:
"""Convert an IPv4 or IPv6 address in textual form into a Name object whose
value is the reverse-map domain name of the address.
try:
v6 = dns.ipv6.inet_aton(text)
if dns.ipv6.is_mapped(v6):
- parts = ['%d' % byte for byte in v6[12:]]
+ parts = ["%d" % byte for byte in v6[12:]]
origin = v4_origin
else:
parts = [x for x in str(binascii.hexlify(v6).decode())]
origin = v6_origin
except Exception:
- parts = ['%d' %
- byte for byte in dns.ipv4.inet_aton(text)]
+ parts = ["%d" % byte for byte in dns.ipv4.inet_aton(text)]
origin = v4_origin
- return dns.name.from_text('.'.join(reversed(parts)), origin=origin)
+ return dns.name.from_text(".".join(reversed(parts)), origin=origin)
-def to_address(name: dns.name.Name, v4_origin: dns.name.Name=ipv4_reverse_domain,
- v6_origin: dns.name.Name=ipv6_reverse_domain) -> str:
+def to_address(
+ name: dns.name.Name,
+ v4_origin: dns.name.Name = ipv4_reverse_domain,
+ v6_origin: dns.name.Name = ipv6_reverse_domain,
+) -> str:
"""Convert a reverse map domain name into textual address form.
*name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name
if name.is_subdomain(v4_origin):
name = name.relativize(v4_origin)
- text = b'.'.join(reversed(name.labels))
+ text = b".".join(reversed(name.labels))
# run through inet_ntoa() to check syntax and make pretty.
return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
elif name.is_subdomain(v6_origin):
labels = list(reversed(name.labels))
parts = []
for i in range(0, len(labels), 4):
- parts.append(b''.join(labels[i:i + 4]))
- text = b':'.join(parts)
+ parts.append(b"".join(labels[i : i + 4]))
+ text = b":".join(parts)
# run through inet_ntoa() to check syntax and make pretty.
return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
else:
- raise dns.exception.SyntaxError('unknown reverse-map address family')
+ raise dns.exception.SyntaxError("unknown reverse-map address family")
name.
"""
- __slots__ = ['name', 'deleting']
-
- def __init__(self, name: dns.name.Name, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- deleting: Optional[dns.rdataclass.RdataClass]=None):
+ __slots__ = ["name", "deleting"]
+
+ def __init__(
+ self,
+ name: dns.name.Name,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ deleting: Optional[dns.rdataclass.RdataClass] = None,
+ ):
"""Create a new RRset."""
super().__init__(rdclass, rdtype, covers)
def __repr__(self):
if self.covers == 0:
- ctext = ''
+ ctext = ""
else:
- ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
+ ctext = "(" + dns.rdatatype.to_text(self.covers) + ")"
if self.deleting is not None:
- dtext = ' delete=' + dns.rdataclass.to_text(self.deleting)
+ dtext = " delete=" + dns.rdataclass.to_text(self.deleting)
else:
- dtext = ''
- return '<DNS ' + str(self.name) + ' ' + \
- dns.rdataclass.to_text(self.rdclass) + ' ' + \
- dns.rdatatype.to_text(self.rdtype) + ctext + dtext + \
- ' RRset: ' + self._rdata_repr() + '>'
+ dtext = ""
+ return (
+ "<DNS "
+ + str(self.name)
+ + " "
+ + dns.rdataclass.to_text(self.rdclass)
+ + " "
+ + dns.rdatatype.to_text(self.rdtype)
+ + ctext
+ + dtext
+ + " RRset: "
+ + self._rdata_repr()
+ + ">"
+ )
def __str__(self):
return self.to_text()
return False
return super().__eq__(other)
- def match(self, *args: Any, **kwargs: Dict[str, Any]) -> bool: # type: ignore[override]
+ def match( # type: ignore[override]
+ self, *args: Any, **kwargs: Dict[str, Any]
+ ) -> bool:
"""Does this rrset match the specified attributes?
Behaves as :py:func:`full_match()` if the first argument is a
else:
return super().match(*args, **kwargs) # type: ignore[arg-type]
- def full_match(self, name: dns.name.Name, rdclass: dns.rdataclass.RdataClass,
- rdtype: dns.rdatatype.RdataType, covers: dns.rdatatype.RdataType,
- deleting: Optional[dns.rdataclass.RdataClass]=None) -> bool:
+ def full_match(
+ self,
+ name: dns.name.Name,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType,
+ deleting: Optional[dns.rdataclass.RdataClass] = None,
+ ) -> bool:
"""Returns ``True`` if this rrset matches the specified name, class,
type, covers, and deletion state.
"""
# pylint: disable=arguments-differ
- def to_text(self, origin: Optional[dns.name.Name]=None, relativize: bool=True, **kw) -> str: # type: ignore
+ def to_text( # type: ignore[override]
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ **kw: Dict[str, Any]
+ ) -> str:
"""Convert the RRset into DNS zone file format.
See ``dns.name.Name.choose_relativity`` for more information
to *origin*.
"""
- return super().to_text(self.name, origin, relativize,
- self.deleting, **kw)
-
- def to_wire(self, file: Any, compress: Optional[dns.name.CompressType]=None, # type: ignore
- origin: Optional[dns.name.Name]=None, **kw) -> int:
+ return super().to_text(
+ self.name, origin, relativize, self.deleting, **kw # type: ignore
+ )
+
+ def to_wire( # type: ignore[override]
+ self,
+ file: Any,
+ compress: Optional[dns.name.CompressType] = None, # type: ignore
+ origin: Optional[dns.name.Name] = None,
+ **kw: Dict[str, Any]
+ ) -> int:
"""Convert the RRset to wire format.
All keyword arguments are passed to ``dns.rdataset.to_wire()``; see
Returns an ``int``, the number of records emitted.
"""
- return super().to_wire(self.name, file, compress, origin,
- self.deleting, **kw)
+ return super().to_wire(
+ self.name, file, compress, origin, self.deleting, **kw # type:ignore
+ )
# pylint: enable=arguments-differ
return dns.rdataset.from_rdata_list(self.ttl, list(self))
-def from_text_list(name: Union[dns.name.Name, str], ttl: int,
- rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- text_rdatas: Collection[str],
- idna_codec: Optional[dns.name.IDNACodec]=None,
- origin: Optional[dns.name.Name]=None, relativize: bool=True,
- relativize_to: Optional[dns.name.Name]=None) -> RRset:
+def from_text_list(
+ name: Union[dns.name.Name, str],
+ ttl: int,
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ text_rdatas: Collection[str],
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = True,
+ relativize_to: Optional[dns.name.Name] = None,
+) -> RRset:
"""Create an RRset with the specified name, TTL, class, and type, and with
the specified list of rdatas in text format.
r = RRset(name, the_rdclass, the_rdtype)
r.update_ttl(ttl)
for t in text_rdatas:
- rd = dns.rdata.from_text(r.rdclass, r.rdtype, t, origin, relativize,
- relativize_to, idna_codec)
+ rd = dns.rdata.from_text(
+ r.rdclass, r.rdtype, t, origin, relativize, relativize_to, idna_codec
+ )
r.add(rd)
return r
-def from_text(name: Union[dns.name.Name, str], ttl: int,
- rdclass: Union[dns.rdataclass.RdataClass, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- *text_rdatas: Any) -> RRset:
+def from_text(
+ name: Union[dns.name.Name, str],
+ ttl: int,
+ rdclass: Union[dns.rdataclass.RdataClass, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ *text_rdatas: Any
+) -> RRset:
"""Create an RRset with the specified name, TTL, class, and type and with
the specified rdatas in text format.
Returns a ``dns.rrset.RRset`` object.
"""
- return from_text_list(name, ttl, rdclass, rdtype,
- cast(Collection[str], text_rdatas))
+ return from_text_list(
+ name, ttl, rdclass, rdtype, cast(Collection[str], text_rdatas)
+ )
-def from_rdata_list(name: Union[dns.name.Name, str], ttl: int,
- rdatas: Collection[dns.rdata.Rdata],
- idna_codec: Optional[dns.name.IDNACodec]=None) -> RRset:
+def from_rdata_list(
+ name: Union[dns.name.Name, str],
+ ttl: int,
+ rdatas: Collection[dns.rdata.Rdata],
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+) -> RRset:
"""Create an RRset with the specified name and TTL, and with
the specified list of rdata objects.
return r
-def from_rdata(name: Union[dns.name.Name, str], ttl:int, *rdatas: Any) -> RRset:
+def from_rdata(name: Union[dns.name.Name, str], ttl: int, *rdatas: Any) -> RRset:
"""Create an RRset with the specified name and TTL, and with
the specified rdata objects.
"""Serial Number Arthimetic from RFC 1982"""
+
class Serial:
- def __init__(self, value: int, bits: int=32):
- self.value = value % 2 ** bits
+ def __init__(self, value: int, bits: int = 32):
+ self.value = value % 2**bits
self.bits = bits
def __repr__(self):
- return f'dns.serial.Serial({self.value}, {self.bits})'
+ return f"dns.serial.Serial({self.value}, {self.bits})"
def __eq__(self, other):
if isinstance(other, int):
other = Serial(other, self.bits)
elif not isinstance(other, Serial) or other.bits != self.bits:
return NotImplemented
- if self.value < other.value and \
- other.value - self.value < 2 ** (self.bits - 1):
+ if self.value < other.value and other.value - self.value < 2 ** (self.bits - 1):
return True
- elif self.value > other.value and \
- self.value - other.value > 2 ** (self.bits - 1):
+ elif self.value > other.value and self.value - other.value > 2 ** (
+ self.bits - 1
+ ):
return True
else:
return False
other = Serial(other, self.bits)
elif not isinstance(other, Serial) or other.bits != self.bits:
return NotImplemented
- if self.value < other.value and \
- other.value - self.value > 2 ** (self.bits - 1):
+ if self.value < other.value and other.value - self.value > 2 ** (self.bits - 1):
return True
- elif self.value > other.value and \
- self.value - other.value < 2 ** (self.bits - 1):
+ elif self.value > other.value and self.value - other.value < 2 ** (
+ self.bits - 1
+ ):
return True
else:
return False
if abs(delta) > (2 ** (self.bits - 1) - 1):
raise ValueError
v += delta
- v = v % 2 ** self.bits
+ v = v % 2**self.bits
return Serial(v, self.bits)
def __iadd__(self, other):
if abs(delta) > (2 ** (self.bits - 1) - 1):
raise ValueError
v += delta
- v = v % 2 ** self.bits
+ v = v % 2**self.bits
self.value = v
return self
if abs(delta) > (2 ** (self.bits - 1) - 1):
raise ValueError
v -= delta
- v = v % 2 ** self.bits
+ v = v % 2**self.bits
return Serial(v, self.bits)
def __isub__(self, other):
if abs(delta) > (2 ** (self.bits - 1) - 1):
raise ValueError
v -= delta
- v = v % 2 ** self.bits
+ v = v % 2**self.bits
self.value = v
return self
ability is widely used in dnspython applications.
"""
- __slots__ = ['items']
+ __slots__ = ["items"]
def __init__(self, items=None):
"""Initialize the set.
return "dns.set.Set(%s)" % repr(list(self.items.keys()))
def add(self, item):
- """Add an item to the set.
- """
+ """Add an item to the set."""
if item not in self.items:
self.items[item] = None
def remove(self, item):
- """Remove an item from the set.
- """
+ """Remove an item from the set."""
try:
del self.items[item]
raise ValueError
def discard(self, item):
- """Remove an item from the set if present.
- """
+ """Remove an item from the set if present."""
self.items.pop(item, None)
(k, _) = self.items.popitem()
return k
- def _clone(self) -> 'Set':
+ def _clone(self) -> "Set":
"""Make a (shallow) copy of the set.
There is a 'clone protocol' that subclasses of this class
subclasses.
"""
- if hasattr(self, '_clone_class'):
- cls = self._clone_class # type: ignore
+ if hasattr(self, "_clone_class"):
+ cls = self._clone_class # type: ignore
else:
cls = self.__class__
obj = cls.__new__(cls)
return obj
def __copy__(self):
- """Make a (shallow) copy of the set.
- """
+ """Make a (shallow) copy of the set."""
return self._clone()
def copy(self):
- """Make a (shallow) copy of the set.
- """
+ """Make a (shallow) copy of the set."""
return self._clone()
"""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
if self is other: # lgtm[py/comparison-using-is]
return
for item in other.items:
"""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
if self is other: # lgtm[py/comparison-using-is]
return
# we make a copy of the list so that we can remove items from
"""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
if self is other: # lgtm[py/comparison-using-is]
self.items.clear()
else:
"""Update the set, retaining only elements unique to both sets."""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
if self is other: # lgtm[py/comparison-using-is]
self.items.clear()
else:
"""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
for item in self.items:
if item not in other.items:
return False
"""
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
for item in other.items:
if item not in self.items:
return False
def isdisjoint(self, other):
if not isinstance(other, Set):
- raise ValueError('other must be a Set instance')
+ raise ValueError("other must be a Set instance")
for item in other.items:
if item in self.items:
return False
"""Tokenize DNS zone file format"""
-from typing import Any, Optional, List, Tuple, Union
+from typing import Any, Optional, List, Tuple
import io
import sys
import dns.name
import dns.ttl
-_DELIMITERS = {' ', '\t', '\n', ';', '(', ')', '"'}
+_DELIMITERS = {" ", "\t", "\n", ";", "(", ")", '"'}
_QUOTING_DELIMITERS = {'"'}
EOF = 0
has_escape: Does the token value contain escapes?
"""
- def __init__(self, ttype: int, value: Any='', has_escape: bool=False,
- comment: Optional[str]=None):
+ def __init__(
+ self,
+ ttype: int,
+ value: Any = "",
+ has_escape: bool = False,
+ comment: Optional[str] = None,
+ ):
"""Initialize a token instance."""
self.ttype = ttype
def __eq__(self, other):
if not isinstance(other, Token):
return False
- return (self.ttype == other.ttype and
- self.value == other.value)
+ return self.ttype == other.ttype and self.value == other.value
def __ne__(self, other):
if not isinstance(other, Token):
return True
- return (self.ttype != other.ttype or
- self.value != other.value)
+ return self.ttype != other.ttype or self.value != other.value
def __str__(self):
return '%d "%s"' % (self.ttype, self.value)
- def unescape(self) -> 'Token':
+ def unescape(self) -> "Token":
if not self.has_escape:
return self
- unescaped = ''
+ unescaped = ""
l = len(self.value)
i = 0
while i < l:
c = self.value[i]
i += 1
- if c == '\\':
+ if c == "\\":
if i >= l: # pragma: no cover (can't happen via get())
raise dns.exception.UnexpectedEnd
c = self.value[i]
unescaped += c
return Token(self.ttype, unescaped)
- def unescape_to_bytes(self) -> 'Token':
+ def unescape_to_bytes(self) -> "Token":
# We used to use unescape() for TXT-like records, but this
# caused problems as we'd process DNS escapes into Unicode code
# points instead of byte values, and then a to_text() of the
#
# foo\226\128\139bar
#
- unescaped = b''
+ unescaped = b""
l = len(self.value)
i = 0
while i < l:
c = self.value[i]
i += 1
- if c == '\\':
+ if c == "\\":
if i >= l: # pragma: no cover (can't happen via get())
raise dns.exception.UnexpectedEnd
c = self.value[i]
codepoint = int(c) * 100 + int(c2) * 10 + int(c3)
if codepoint > 255:
raise dns.exception.SyntaxError
- unescaped += b'%c' % (codepoint)
+ unescaped += b"%c" % (codepoint)
else:
# Note that as mentioned above, if c is a Unicode
# code point outside of the ASCII range, then this
encoder/decoder is used.
"""
- def __init__(self, f: Any=sys.stdin, filename: Optional[str]=None,
- idna_codec: Optional[dns.name.IDNACodec]=None):
+ def __init__(
+ self,
+ f: Any = sys.stdin,
+ filename: Optional[str] = None,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ ):
"""Initialize a tokenizer instance.
f: The file to tokenize. The default is sys.stdin.
if isinstance(f, str):
f = io.StringIO(f)
if filename is None:
- filename = '<string>'
+ filename = "<string>"
elif isinstance(f, bytes):
f = io.StringIO(f.decode())
if filename is None:
- filename = '<string>'
+ filename = "<string>"
else:
if filename is None:
if f is sys.stdin:
- filename = '<stdin>'
+ filename = "<stdin>"
else:
- filename = '<file>'
+ filename = "<file>"
self.file = f
self.ungotten_char: Optional[str] = None
self.ungotten_token: Optional[Token] = None
self.idna_codec = idna_codec
def _get_char(self) -> str:
- """Read a character from input.
- """
+ """Read a character from input."""
if self.ungotten_char is None:
if self.eof:
- c = ''
+ c = ""
else:
c = self.file.read(1)
- if c == '':
+ if c == "":
self.eof = True
- elif c == '\n':
+ elif c == "\n":
self.line_number += 1
else:
c = self.ungotten_char
skipped = 0
while True:
c = self._get_char()
- if c != ' ' and c != '\t':
- if (c != '\n') or not self.multiline:
+ if c != " " and c != "\t":
+ if (c != "\n") or not self.multiline:
self._unget_char(c)
return skipped
skipped += 1
- def get(self, want_leading: bool=False, want_comment: bool=False) -> Token:
+ def get(self, want_leading: bool = False, want_comment: bool = False) -> Token:
"""Get the next token.
want_leading: If True, return a WHITESPACE token if the
return utoken
skipped = self.skip_whitespace()
if want_leading and skipped > 0:
- return Token(WHITESPACE, ' ')
- token = ''
+ return Token(WHITESPACE, " ")
+ token = ""
ttype = IDENTIFIER
has_escape = False
while True:
c = self._get_char()
- if c == '' or c in self.delimiters:
- if c == '' and self.quoting:
+ if c == "" or c in self.delimiters:
+ if c == "" and self.quoting:
raise dns.exception.UnexpectedEnd
- if token == '' and ttype != QUOTED_STRING:
- if c == '(':
+ if token == "" and ttype != QUOTED_STRING:
+ if c == "(":
self.multiline += 1
self.skip_whitespace()
continue
- elif c == ')':
+ elif c == ")":
if self.multiline <= 0:
raise dns.exception.SyntaxError
self.multiline -= 1
self.delimiters = _DELIMITERS
self.skip_whitespace()
continue
- elif c == '\n':
- return Token(EOL, '\n')
- elif c == ';':
+ elif c == "\n":
+ return Token(EOL, "\n")
+ elif c == ";":
while 1:
c = self._get_char()
- if c == '\n' or c == '':
+ if c == "\n" or c == "":
break
token += c
if want_comment:
self._unget_char(c)
return Token(COMMENT, token)
- elif c == '':
+ elif c == "":
if self.multiline:
raise dns.exception.SyntaxError(
- 'unbalanced parentheses')
+ "unbalanced parentheses"
+ )
return Token(EOF, comment=token)
elif self.multiline:
self.skip_whitespace()
- token = ''
+ token = ""
continue
else:
- return Token(EOL, '\n', comment=token)
+ return Token(EOL, "\n", comment=token)
else:
# This code exists in case we ever want a
# delimiter to be returned. It never produces
else:
self._unget_char(c)
break
- elif self.quoting and c == '\n':
- raise dns.exception.SyntaxError('newline in quoted string')
- elif c == '\\':
+ elif self.quoting and c == "\n":
+ raise dns.exception.SyntaxError("newline in quoted string")
+ elif c == "\\":
#
# It's an escape. Put it and the next character into
# the token; it will be checked later for goodness.
token += c
has_escape = True
c = self._get_char()
- if c == '' or (c == '\n' and not self.quoting):
+ if c == "" or (c == "\n" and not self.quoting):
raise dns.exception.UnexpectedEnd
token += c
- if token == '' and ttype != QUOTED_STRING:
+ if token == "" and ttype != QUOTED_STRING:
if self.multiline:
- raise dns.exception.SyntaxError('unbalanced parentheses')
+ raise dns.exception.SyntaxError("unbalanced parentheses")
ttype = EOF
return Token(ttype, token, has_escape)
# Helpers
- def get_int(self, base: int=10) -> int:
+ def get_int(self, base: int = 10) -> int:
"""Read the next token and interpret it as an unsigned integer.
Raises dns.exception.SyntaxError if not an unsigned integer.
token = self.get().unescape()
if not token.is_identifier():
- raise dns.exception.SyntaxError('expecting an identifier')
+ raise dns.exception.SyntaxError("expecting an identifier")
if not token.value.isdigit():
- raise dns.exception.SyntaxError('expecting an integer')
+ raise dns.exception.SyntaxError("expecting an integer")
return int(token.value, base)
def get_uint8(self) -> int:
value = self.get_int()
if value < 0 or value > 255:
raise dns.exception.SyntaxError(
- '%d is not an unsigned 8-bit integer' % value)
+ "%d is not an unsigned 8-bit integer" % value
+ )
return value
- def get_uint16(self, base: int=10) -> int:
+ def get_uint16(self, base: int = 10) -> int:
"""Read the next token and interpret it as a 16-bit unsigned
integer.
if value < 0 or value > 65535:
if base == 8:
raise dns.exception.SyntaxError(
- '%o is not an octal unsigned 16-bit integer' % value)
+ "%o is not an octal unsigned 16-bit integer" % value
+ )
else:
raise dns.exception.SyntaxError(
- '%d is not an unsigned 16-bit integer' % value)
+ "%d is not an unsigned 16-bit integer" % value
+ )
return value
- def get_uint32(self, base: int=10) -> int:
+ def get_uint32(self, base: int = 10) -> int:
"""Read the next token and interpret it as a 32-bit unsigned
integer.
value = self.get_int(base=base)
if value < 0 or value > 4294967295:
raise dns.exception.SyntaxError(
- '%d is not an unsigned 32-bit integer' % value)
+ "%d is not an unsigned 32-bit integer" % value
+ )
return value
- def get_uint48(self, base: int=10) -> int:
+ def get_uint48(self, base: int = 10) -> int:
"""Read the next token and interpret it as a 48-bit unsigned
integer.
value = self.get_int(base=base)
if value < 0 or value > 281474976710655:
raise dns.exception.SyntaxError(
- '%d is not an unsigned 48-bit integer' % value)
+ "%d is not an unsigned 48-bit integer" % value
+ )
return value
- def get_string(self, max_length: Optional[int]=None) -> str:
+ def get_string(self, max_length: Optional[int] = None) -> str:
"""Read the next token and interpret it as a string.
Raises dns.exception.SyntaxError if not a string.
token = self.get().unescape()
if not (token.is_identifier() or token.is_quoted_string()):
- raise dns.exception.SyntaxError('expecting a string')
+ raise dns.exception.SyntaxError("expecting a string")
if max_length and len(token.value) > max_length:
raise dns.exception.SyntaxError("string too long")
return token.value
token = self.get().unescape()
if not token.is_identifier():
- raise dns.exception.SyntaxError('expecting an identifier')
+ raise dns.exception.SyntaxError("expecting an identifier")
return token.value
- def get_remaining(self, max_tokens: Optional[int]=None) -> List[Token]:
+ def get_remaining(self, max_tokens: Optional[int] = None) -> List[Token]:
"""Return the remaining tokens on the line, until an EOL or EOF is seen.
max_tokens: If not None, stop after this number of tokens.
break
return tokens
- def concatenate_remaining_identifiers(self, allow_empty: bool=False) -> str:
+ def concatenate_remaining_identifiers(self, allow_empty: bool = False) -> str:
"""Read the remaining tokens on the line, which should be identifiers.
Raises dns.exception.SyntaxError if there are no remaining tokens,
raise dns.exception.SyntaxError
s += token.value
if not (allow_empty or s):
- raise dns.exception.SyntaxError('expecting another identifier')
+ raise dns.exception.SyntaxError("expecting another identifier")
return s
- def as_name(self, token: Token, origin: Optional[dns.name.Name]=None,
- relativize: bool=False, relativize_to: Optional[dns.name.Name]=None) -> dns.name.Name:
+ def as_name(
+ self,
+ token: Token,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = False,
+ relativize_to: Optional[dns.name.Name] = None,
+ ) -> dns.name.Name:
"""Try to interpret the token as a DNS name.
Raises dns.exception.SyntaxError if not a name.
Returns a dns.name.Name.
"""
if not token.is_identifier():
- raise dns.exception.SyntaxError('expecting an identifier')
+ raise dns.exception.SyntaxError("expecting an identifier")
name = dns.name.from_text(token.value, origin, self.idna_codec)
return name.choose_relativity(relativize_to or origin, relativize)
- def get_name(self, origin: Optional[dns.name.Name]=None, relativize: bool=False,
- relativize_to: Optional[dns.name.Name]=None) -> dns.name.Name:
+ def get_name(
+ self,
+ origin: Optional[dns.name.Name] = None,
+ relativize: bool = False,
+ relativize_to: Optional[dns.name.Name] = None,
+ ) -> dns.name.Name:
"""Read the next token and interpret it as a DNS name.
Raises dns.exception.SyntaxError if not a name.
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))
+ 'expected EOL or EOF, got %d "%s"' % (token.ttype, token.value)
+ )
return token
def get_eol(self) -> str:
token = self.get().unescape()
if not token.is_identifier():
- raise dns.exception.SyntaxError('expecting an identifier')
+ raise dns.exception.SyntaxError("expecting an identifier")
return dns.ttl.from_text(token.value)
class TransactionManager:
- def reader(self) -> 'Transaction':
+ def reader(self) -> "Transaction":
"""Begin a read-only transaction."""
raise NotImplementedError # pragma: no cover
- def writer(self, replacement: bool=False) -> 'Transaction':
+ def writer(self, replacement: bool = False) -> "Transaction":
"""Begin a writable transaction.
*replacement*, a ``bool``. If `True`, the content of the
"""
raise NotImplementedError # pragma: no cover
- def origin_information(self) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]:
+ def origin_information(
+ self,
+ ) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]:
"""Returns a tuple
(absolute_origin, relativize, effective_origin)
raise NotImplementedError # pragma: no cover
def get_class(self) -> dns.rdataclass.RdataClass:
- """The class of the transaction manager.
- """
+ """The class of the transaction manager."""
raise NotImplementedError # pragma: no cover
def from_wire_origin(self) -> Optional[dns.name.Name]:
- """Origin to use in from_wire() calls.
- """
+ """Origin to use in from_wire() calls."""
(absolute_origin, relativize, _) = self.origin_information()
if relativize:
return absolute_origin
return rdataset
return dns.rdataset.ImmutableRdataset(rdataset)
+
def _ensure_immutable_node(node):
if node is None or node.is_immutable():
return node
return dns.node.ImmutableNode(node)
-CheckPutRdatasetType = Callable[['Transaction', dns.name.Name, dns.rdataset.Rdataset], None]
-CheckDeleteRdatasetType = Callable[['Transaction', dns.name.Name,
- dns.rdatatype.RdataType, dns.rdatatype.RdataType], None]
-CheckDeleteNameType = Callable[['Transaction', dns.name.Name], None]
+CheckPutRdatasetType = Callable[
+ ["Transaction", dns.name.Name, dns.rdataset.Rdataset], None
+]
+CheckDeleteRdatasetType = Callable[
+ ["Transaction", dns.name.Name, dns.rdatatype.RdataType, dns.rdatatype.RdataType],
+ None,
+]
+CheckDeleteNameType = Callable[["Transaction", dns.name.Name], None]
class Transaction:
-
- def __init__(self, manager: TransactionManager, replacement: bool=False, read_only: bool=False):
+ def __init__(
+ self,
+ manager: TransactionManager,
+ replacement: bool = False,
+ read_only: bool = False,
+ ):
self.manager = manager
self.replacement = replacement
self.read_only = read_only
self._ended = False
- self._check_put_rdataset: List[CheckPutRdatasetType]= []
+ self._check_put_rdataset: List[CheckPutRdatasetType] = []
self._check_delete_rdataset: List[CheckDeleteRdatasetType] = []
self._check_delete_name: List[CheckDeleteNameType] = []
#
# This is the high level API
#
- # Note that we currently use non-immutable types in the return type signature to avoid
- # covariance problems, e.g. if the caller has a List[Rdataset], mypy will be unhappy if we
- # return an ImmutableRdataset.
-
- def get(self, name: Optional[Union[dns.name.Name,str]],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) -> dns.rdataset.Rdataset:
+ # Note that we currently use non-immutable types in the return type signature to
+ # avoid covariance problems, e.g. if the caller has a List[Rdataset], mypy will be
+ # unhappy if we return an ImmutableRdataset.
+
+ def get(
+ self,
+ name: Optional[Union[dns.name.Name, str]],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> dns.rdataset.Rdataset:
"""Return the rdataset associated with *name*, *rdtype*, and *covers*,
or `None` if not found.
name = dns.name.from_text(name, None)
return self._name_exists(name)
- def update_serial(self, value: int=1, relative: bool=True, name: dns.name.Name=dns.name.empty) -> None:
+ def update_serial(
+ self,
+ value: int = 1,
+ relative: bool = True,
+ name: dns.name.Name = dns.name.empty,
+ ) -> None:
"""Update the serial number.
*value*, an `int`, is an increment if *relative* is `True`, or the
"""
self._check_ended()
if value < 0:
- raise ValueError('negative update_serial() value')
+ raise ValueError("negative update_serial() value")
if isinstance(name, str):
name = dns.name.from_text(name, None)
- rdataset = self._get_rdataset(name, dns.rdatatype.SOA,
- dns.rdatatype.NONE)
+ rdataset = self._get_rdataset(name, dns.rdatatype.SOA, dns.rdatatype.NONE)
if rdataset is None or len(rdataset) == 0:
raise KeyError
if relative:
def _raise_if_not_empty(self, method, args):
if len(args) != 0:
- raise TypeError(f'extra parameters to {method}')
+ raise TypeError(f"extra parameters to {method}")
def _rdataset_from_args(self, method, deleting, args):
try:
if isinstance(arg, int):
ttl = arg
if ttl > dns.ttl.MAX_TTL:
- raise ValueError(f'{method}: TTL value too big')
+ raise ValueError(f"{method}: TTL value too big")
else:
- raise TypeError(f'{method}: expected a TTL')
+ raise TypeError(f"{method}: expected a TTL")
arg = args.popleft()
if isinstance(arg, dns.rdata.Rdata):
rdataset = dns.rdataset.from_rdata(ttl, arg)
else:
- raise TypeError(f'{method}: expected an Rdata')
+ raise TypeError(f"{method}: expected an Rdata")
return rdataset
except IndexError:
if deleting:
return None
else:
# reraise
- raise TypeError(f'{method}: expected more arguments')
+ raise TypeError(f"{method}: expected more arguments")
def _add(self, replace, args):
try:
args = collections.deque(args)
if replace:
- method = 'replace()'
+ method = "replace()"
else:
- method = 'add()'
+ method = "add()"
arg = args.popleft()
if isinstance(arg, str):
arg = dns.name.from_text(arg, None)
# same and can't be stored in nodes, so convert.
rdataset = rrset.to_rdataset()
else:
- raise TypeError(f'{method} requires a name or RRset ' +
- 'as the first argument')
+ raise TypeError(
+ f"{method} requires a name or RRset " + "as the first argument"
+ )
if rdataset.rdclass != self.manager.get_class():
- raise ValueError(f'{method} has objects of wrong RdataClass')
+ raise ValueError(f"{method} has objects of wrong RdataClass")
if rdataset.rdtype == dns.rdatatype.SOA:
(_, _, origin) = self._origin_information()
if name != origin:
- raise ValueError(f'{method} has non-origin SOA')
+ raise ValueError(f"{method} has non-origin SOA")
self._raise_if_not_empty(method, args)
if not replace:
- existing = self._get_rdataset(name, rdataset.rdtype,
- rdataset.covers)
+ existing = self._get_rdataset(name, rdataset.rdtype, rdataset.covers)
if existing is not None:
if isinstance(existing, dns.rdataset.ImmutableRdataset):
- trds = dns.rdataset.Rdataset(existing.rdclass,
- existing.rdtype,
- existing.covers)
+ trds = dns.rdataset.Rdataset(
+ existing.rdclass, existing.rdtype, existing.covers
+ )
trds.update(existing)
existing = trds
rdataset = existing.union(rdataset)
self._checked_put_rdataset(name, rdataset)
except IndexError:
- raise TypeError(f'not enough parameters to {method}')
+ raise TypeError(f"not enough parameters to {method}")
def _delete(self, exact, args):
try:
args = collections.deque(args)
if exact:
- method = 'delete_exact()'
+ method = "delete_exact()"
else:
- method = 'delete()'
+ method = "delete()"
arg = args.popleft()
if isinstance(arg, str):
arg = dns.name.from_text(arg, None)
if isinstance(arg, dns.name.Name):
name = arg
- if len(args) > 0 and (isinstance(args[0], int) or
- isinstance(args[0], str)):
+ if len(args) > 0 and (
+ isinstance(args[0], int) or isinstance(args[0], str)
+ ):
# deleting by type and (optionally) covers
rdtype = dns.rdatatype.RdataType.make(args.popleft())
if len(args) > 0:
existing = self._get_rdataset(name, rdtype, covers)
if existing is None:
if exact:
- raise DeleteNotExact(f'{method}: missing rdataset')
+ raise DeleteNotExact(f"{method}: missing rdataset")
else:
self._delete_rdataset(name, rdtype, covers)
return
rdataset = arg # rrsets are also rdatasets
name = rdataset.name
else:
- raise TypeError(f'{method} requires a name or RRset ' +
- 'as the first argument')
+ raise TypeError(
+ f"{method} requires a name or RRset " + "as the first argument"
+ )
self._raise_if_not_empty(method, args)
if rdataset:
if rdataset.rdclass != self.manager.get_class():
- raise ValueError(f'{method} has objects of wrong '
- 'RdataClass')
- existing = self._get_rdataset(name, rdataset.rdtype,
- rdataset.covers)
+ raise ValueError(f"{method} has objects of wrong " "RdataClass")
+ existing = self._get_rdataset(name, rdataset.rdtype, rdataset.covers)
if existing is not None:
if exact:
intersection = existing.intersection(rdataset)
if intersection != rdataset:
- raise DeleteNotExact(f'{method}: missing rdatas')
+ raise DeleteNotExact(f"{method}: missing rdatas")
rdataset = existing.difference(rdataset)
if len(rdataset) == 0:
- self._checked_delete_rdataset(name, rdataset.rdtype,
- rdataset.covers)
+ self._checked_delete_rdataset(
+ name, rdataset.rdtype, rdataset.covers
+ )
else:
self._checked_put_rdataset(name, rdataset)
elif exact:
- raise DeleteNotExact(f'{method}: missing rdataset')
+ raise DeleteNotExact(f"{method}: missing rdataset")
else:
if exact and not self._name_exists(name):
- raise DeleteNotExact(f'{method}: name not known')
+ raise DeleteNotExact(f"{method}: name not known")
self._checked_delete_name(name)
except IndexError:
- raise TypeError(f'not enough parameters to {method}')
+ raise TypeError(f"not enough parameters to {method}")
def _check_ended(self):
if self._ended:
raise NotImplementedError # pragma: no cover
def _iterate_rdatasets(self):
- """Return an iterator that yields (name, rdataset) tuples.
- """
+ """Return an iterator that yields (name, rdataset) tuples."""
raise NotImplementedError # pragma: no cover
def _get_node(self, name):
import dns.name
import dns.rcode
+
class BadTime(dns.exception.DNSException):
"""The current time is not within the TSIG's validity time."""
In order to avoid a direct GSSAPI dependency, the keyring holds a ref
to the GSSAPI object required, rather than the key itself.
"""
+
def __init__(self, gssapi_context):
self.gssapi_context = gssapi_context
- self.data = b''
- self.name = 'gss-tsig'
+ self.data = b""
+ self.name = "gss-tsig"
def update(self, data):
self.data += data
# client to complete the GSSAPI negotiation before attempting
# to verify the signed response to a TKEY message exchange
try:
- rrset = message.find_rrset(message.answer, keyname,
- dns.rdataclass.ANY,
- dns.rdatatype.TKEY)
+ rrset = message.find_rrset(
+ message.answer, keyname, dns.rdataclass.ANY, dns.rdatatype.TKEY
+ )
if rrset:
token = rrset[0].key
gssapi_context = key.secret
try:
hashinfo = self._hashes[algorithm]
except KeyError:
- raise NotImplementedError(f"TSIG algorithm {algorithm} " +
- "is not supported")
+ raise NotImplementedError(
+ f"TSIG algorithm {algorithm} " + "is not supported"
+ )
# create the HMAC context
if isinstance(hashinfo, tuple):
self.size = None
self.name = self.hmac_context.name
if self.size:
- self.name += f'-{self.size}'
+ self.name += f"-{self.size}"
def update(self, data):
return self.hmac_context.update(data)
raise BadSignature
-def _digest(wire, key, rdata, time=None, request_mac=None, ctx=None,
- multi=None):
+def _digest(wire, key, rdata, time=None, request_mac=None, ctx=None, multi=None):
"""Return a context containing the TSIG rdata for the input parameters
@rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object
@raises ValueError: I{other_data} is too long
if first:
ctx = get_context(key)
if request_mac:
- ctx.update(struct.pack('!H', len(request_mac)))
+ ctx.update(struct.pack("!H", len(request_mac)))
ctx.update(request_mac)
- ctx.update(struct.pack('!H', rdata.original_id))
+ ctx.update(struct.pack("!H", rdata.original_id))
ctx.update(wire[2:])
if first:
ctx.update(key.name.to_digestable())
- ctx.update(struct.pack('!H', dns.rdataclass.ANY))
- ctx.update(struct.pack('!I', 0))
+ ctx.update(struct.pack("!H", dns.rdataclass.ANY))
+ ctx.update(struct.pack("!I", 0))
if time is None:
time = rdata.time_signed
- upper_time = (time >> 32) & 0xffff
- lower_time = time & 0xffffffff
- time_encoded = struct.pack('!HIH', upper_time, lower_time, rdata.fudge)
+ upper_time = (time >> 32) & 0xFFFF
+ lower_time = time & 0xFFFFFFFF
+ time_encoded = struct.pack("!HIH", upper_time, lower_time, rdata.fudge)
other_len = len(rdata.other)
if other_len > 65535:
- raise ValueError('TSIG Other Data is > 65535 bytes')
+ raise ValueError("TSIG Other Data is > 65535 bytes")
if first:
ctx.update(key.algorithm.to_digestable() + time_encoded)
- ctx.update(struct.pack('!HH', rdata.error, other_len) + rdata.other)
+ ctx.update(struct.pack("!HH", rdata.error, other_len) + rdata.other)
else:
ctx.update(time_encoded)
return ctx
"""
if multi:
ctx = get_context(key)
- ctx.update(struct.pack('!H', len(mac)))
+ ctx.update(struct.pack("!H", len(mac)))
ctx.update(mac)
return ctx
else:
return (tsig, _maybe_start_digest(key, mac, multi))
-def validate(wire, key, owner, rdata, now, request_mac, tsig_start, ctx=None,
- multi=False):
+def validate(
+ wire, key, owner, rdata, now, request_mac, tsig_start, ctx=None, multi=False
+):
"""Validate the specified TSIG rdata against the other input parameters.
@raises FormError: The TSIG is badly formed.
elif rdata.error == dns.rcode.BADTRUNC:
raise PeerBadTruncation
else:
- raise PeerError('unknown TSIG error code %d' % rdata.error)
+ raise PeerError("unknown TSIG error code %d" % rdata.error)
if abs(rdata.time_signed - now) > rdata.fudge:
raise BadTime
if key.name != owner:
self.algorithm = algorithm
def __eq__(self, other):
- return (isinstance(other, Key) and
- self.name == other.name and
- self.secret == other.secret and
- self.algorithm == other.algorithm)
+ return (
+ isinstance(other, Key)
+ and self.name == other.name
+ and self.secret == other.secret
+ and self.algorithm == other.algorithm
+ )
def __repr__(self):
- r = f"<DNS key name='{self.name}', " + \
- f"algorithm='{self.algorithm}'"
+ r = f"<DNS key name='{self.name}', " + f"algorithm='{self.algorithm}'"
if self.algorithm != GSS_TSIG:
r += f", secret='{base64.b64encode(self.secret).decode()}'"
r += ">"
@rtype: dict"""
textring = {}
+
def b64encode(secret):
return base64.encodebytes(secret).decode().rstrip()
+
for (name, key) in keyring.items():
tname = name.to_text()
if isinstance(key, bytes):
if need_digit:
raise BadTTL
c = c.lower()
- if c == 'w':
+ if c == "w":
total += current * 604800
- elif c == 'd':
+ elif c == "d":
total += current * 86400
- elif c == 'h':
+ elif c == "h":
total += current * 3600
- elif c == 'm':
+ elif c == "m":
total += current * 60
- elif c == 's':
+ elif c == "s":
total += current
else:
raise BadTTL("unknown unit '%s'" % c)
elif isinstance(value, str):
return dns.ttl.from_text(value)
else:
- raise ValueError('cannot convert value to TTL')
+ raise ValueError("cannot convert value to TTL")
class UpdateSection(dns.enum.IntEnum):
"""Update sections"""
+
ZONE = 0
PREREQ = 1
UPDATE = 2
# ignore the mypy error here as we mean to use a different enum
_section_enum = UpdateSection # type: ignore
- def __init__(self, zone: Optional[Union[dns.name.Name, str]]=None,
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN,
- keyring: Optional[Any]=None, keyname: Optional[dns.name.Name]=None,
- keyalgorithm: Union[dns.name.Name, str]=dns.tsig.default_algorithm,
- id: Optional[int]=None):
+ def __init__(
+ self,
+ zone: Optional[Union[dns.name.Name, str]] = None,
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ keyring: Optional[Any] = None,
+ keyname: Optional[dns.name.Name] = None,
+ keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm,
+ id: Optional[int] = None,
+ ):
"""Initialize a new DNS Update object.
See the documentation of the Message class for a complete
rdclass = dns.rdataclass.RdataClass.make(rdclass)
self.zone_rdclass = rdclass
if self.origin:
- self.find_rrset(self.zone, self.origin, rdclass, dns.rdatatype.SOA,
- create=True, force_unique=True)
+ self.find_rrset(
+ self.zone,
+ self.origin,
+ rdclass,
+ dns.rdatatype.SOA,
+ create=True,
+ force_unique=True,
+ )
if keyring is not None:
self.use_tsig(keyring, keyname, algorithm=keyalgorithm)
if section is None:
section = self.update
covers = rd.covers()
- rrset = self.find_rrset(section, name, self.zone_rdclass, rd.rdtype,
- covers, deleting, True, True)
+ rrset = self.find_rrset(
+ section, name, self.zone_rdclass, rd.rdtype, covers, deleting, True, True
+ )
rrset.add(rd, ttl)
def _add(self, replace, section, name, *args):
if replace:
self.delete(name, rdtype)
for s in args:
- rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s,
- self.origin)
+ rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, self.origin)
self._add_rr(name, ttl, rd, section=section)
def add(self, name: Union[dns.name.Name, str], *args: Any) -> None:
if isinstance(name, str):
name = dns.name.from_text(name, None)
if len(args) == 0:
- self.find_rrset(self.update, name, dns.rdataclass.ANY,
- dns.rdatatype.ANY, dns.rdatatype.NONE,
- dns.rdataclass.ANY, True, True)
+ self.find_rrset(
+ self.update,
+ name,
+ dns.rdataclass.ANY,
+ dns.rdatatype.ANY,
+ dns.rdatatype.NONE,
+ dns.rdataclass.ANY,
+ True,
+ True,
+ )
elif isinstance(args[0], dns.rdataset.Rdataset):
for rds in args:
for rd in rds:
else:
rdtype = dns.rdatatype.RdataType.make(largs.pop(0))
if len(largs) == 0:
- self.find_rrset(self.update, name,
- self.zone_rdclass, rdtype,
- dns.rdatatype.NONE,
- dns.rdataclass.ANY,
- True, True)
+ self.find_rrset(
+ self.update,
+ name,
+ self.zone_rdclass,
+ rdtype,
+ dns.rdatatype.NONE,
+ dns.rdataclass.ANY,
+ True,
+ True,
+ )
else:
for s in largs:
- rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, # type: ignore[arg-type]
- self.origin)
+ rd = dns.rdata.from_text(
+ self.zone_rdclass,
+ rdtype,
+ s, # type: ignore[arg-type]
+ self.origin,
+ )
self._add_rr(name, 0, rd, dns.rdataclass.NONE)
def replace(self, name: Union[dns.name.Name, str], *args: Any) -> None:
if isinstance(name, str):
name = dns.name.from_text(name, None)
if len(args) == 0:
- self.find_rrset(self.prerequisite, 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:
+ self.find_rrset(
+ self.prerequisite,
+ 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
+ ):
if not isinstance(args[0], dns.rdataset.Rdataset):
# Add a 0 TTL
largs = list(args)
self._add(False, self.prerequisite, name, *args)
else:
rdtype = dns.rdatatype.RdataType.make(args[0])
- self.find_rrset(self.prerequisite, name,
- dns.rdataclass.ANY, rdtype,
- dns.rdatatype.NONE, None,
- True, True)
-
- def absent(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str]=None) -> None:
+ self.find_rrset(
+ self.prerequisite,
+ name,
+ dns.rdataclass.ANY,
+ rdtype,
+ dns.rdatatype.NONE,
+ None,
+ True,
+ True,
+ )
+
+ def absent(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str] = None,
+ ) -> 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):
name = dns.name.from_text(name, None)
if rdtype is None:
- self.find_rrset(self.prerequisite, name,
- dns.rdataclass.NONE, dns.rdatatype.ANY,
- dns.rdatatype.NONE, None,
- True, True)
+ self.find_rrset(
+ self.prerequisite,
+ name,
+ dns.rdataclass.NONE,
+ dns.rdatatype.ANY,
+ dns.rdatatype.NONE,
+ None,
+ True,
+ True,
+ )
else:
the_rdtype = dns.rdatatype.RdataType.make(rdtype)
- self.find_rrset(self.prerequisite, name,
- dns.rdataclass.NONE, the_rdtype,
- dns.rdatatype.NONE, None,
- True, True)
+ self.find_rrset(
+ self.prerequisite,
+ name,
+ dns.rdataclass.NONE,
+ the_rdtype,
+ dns.rdatatype.NONE,
+ None,
+ True,
+ True,
+ )
def _get_one_rr_per_rrset(self, value):
# Updates are always one_rr_per_rrset
deleting = None
empty = False
if section == UpdateSection.ZONE:
- if dns.rdataclass.is_metaclass(rdclass) or \
- rdtype != dns.rdatatype.SOA or \
- self.zone:
+ if (
+ dns.rdataclass.is_metaclass(rdclass)
+ or rdtype != dns.rdatatype.SOA
+ or self.zone
+ ):
raise dns.exception.FormError
else:
if not self.zone:
if rdclass in (dns.rdataclass.ANY, dns.rdataclass.NONE):
deleting = rdclass
rdclass = self.zone[0].rdclass
- empty = (deleting == dns.rdataclass.ANY or
- section == UpdateSection.PREREQ)
+ empty = (
+ deleting == dns.rdataclass.ANY or section == UpdateSection.PREREQ
+ )
return (rdclass, rdtype, deleting, empty)
+
# backwards compatibility
Update = UpdateMessage
#: SERIAL
SERIAL = 0
-if RELEASELEVEL == 0x0f: # pragma: no cover lgtm[py/unreachable-statement]
+if RELEASELEVEL == 0x0F: # pragma: no cover lgtm[py/unreachable-statement]
#: version
- version = '%d.%d.%d' % (MAJOR, MINOR, MICRO) # lgtm[py/unreachable-statement]
+ version = "%d.%d.%d" % (MAJOR, MINOR, MICRO) # lgtm[py/unreachable-statement]
elif RELEASELEVEL == 0x00: # pragma: no cover lgtm[py/unreachable-statement]
- version = '%d.%d.%ddev%d' % (MAJOR, MINOR, MICRO, SERIAL) # lgtm[py/unreachable-statement]
-elif RELEASELEVEL == 0x0c: # pragma: no cover lgtm[py/unreachable-statement]
- version = '%d.%d.%drc%d' % (MAJOR, MINOR, MICRO, SERIAL) # lgtm[py/unreachable-statement]
+ version = "%d.%d.%ddev%d" % (
+ MAJOR,
+ MINOR,
+ MICRO,
+ SERIAL,
+ ) # lgtm[py/unreachable-statement]
+elif RELEASELEVEL == 0x0C: # pragma: no cover lgtm[py/unreachable-statement]
+ version = "%d.%d.%drc%d" % (
+ MAJOR,
+ MINOR,
+ MICRO,
+ SERIAL,
+ ) # lgtm[py/unreachable-statement]
else: # pragma: no cover lgtm[py/unreachable-statement]
- version = '%d.%d.%d%x%d' % (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL) # lgtm[py/unreachable-statement]
+ version = "%d.%d.%d%x%d" % (
+ MAJOR,
+ MINOR,
+ MICRO,
+ RELEASELEVEL,
+ SERIAL,
+ ) # lgtm[py/unreachable-statement]
#: hexversion
-hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \
- SERIAL
+hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | SERIAL
from typing import Callable, Deque, Optional, Set, Union
import collections
+
try:
import threading as _threading
except ImportError: # pragma: no cover
- import dummy_threading as _threading # type: ignore
+ import dummy_threading as _threading # type: ignore
import dns.exception
import dns.immutable
class Zone(dns.zone.Zone): # lgtm[py/missing-equals]
- __slots__ = ['_versions', '_versions_lock', '_write_txn',
- '_write_waiters', '_write_event', '_pruning_policy',
- '_readers']
+ __slots__ = [
+ "_versions",
+ "_versions_lock",
+ "_write_txn",
+ "_write_waiters",
+ "_write_event",
+ "_pruning_policy",
+ "_readers",
+ ]
node_factory = Node
- def __init__(self, origin: Optional[Union[dns.name.Name, str]],
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN, relativize: bool=True,
- pruning_policy: Optional[Callable[['Zone', Version], Optional[bool]]]=None):
+ def __init__(
+ self,
+ origin: Optional[Union[dns.name.Name, str]],
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ relativize: bool = True,
+ pruning_policy: Optional[Callable[["Zone", Version], Optional[bool]]] = None,
+ ):
"""Initialize a versioned zone object.
*origin* is the origin of the zone. It may be a ``dns.name.Name``,
self._write_event: Optional[_threading.Event] = None
self._write_waiters: Deque[_threading.Event] = collections.deque()
self._readers: Set[Transaction] = set()
- self._commit_version_unlocked(None,
- WritableVersion(self, replacement=True),
- origin)
+ self._commit_version_unlocked(
+ None, WritableVersion(self, replacement=True), origin
+ )
- def reader(self, id: Optional[int]=None, serial: Optional[int]=None) -> Transaction: # pylint: disable=arguments-differ
+ def reader(
+ self, id: Optional[int] = None, serial: Optional[int] = None
+ ) -> Transaction: # pylint: disable=arguments-differ
if id is not None and serial is not None:
- raise ValueError('cannot specify both id and serial')
+ raise ValueError("cannot specify both id and serial")
with self._version_lock:
if id is not None:
version = None
version = v
break
if version is None:
- raise KeyError('version not found')
+ raise KeyError("version not found")
elif serial is not None:
if self.relativize:
oname = dns.name.empty
version = v
break
if version is None:
- raise KeyError('serial not found')
+ raise KeyError("serial not found")
else:
version = self._versions[-1]
txn = Transaction(self, False, version)
self._readers.add(txn)
return txn
- def writer(self, replacement: bool=False) -> Transaction:
+ def writer(self, replacement: bool = False) -> Transaction:
event = None
while True:
with self._version_lock:
# give up the lock, so that we hold the lock as
# short a time as possible. This is why we call
# _setup_version() below.
- self._write_txn = Transaction(self, replacement,
- make_immutable=True)
+ self._write_txn = Transaction(
+ self, replacement, make_immutable=True
+ )
# give up our exclusive right to make a Transaction
self._write_event = None
break
# pylint: disable=unused-argument
def _default_pruning_policy(self, zone, version):
return True
+
# pylint: enable=unused-argument
def _prune_versions_unlocked(self):
least_kept = min(txn.version.id for txn in self._readers)
else:
least_kept = self._versions[-1].id
- while self._versions[0].id < least_kept and \
- self._pruning_policy(self, self._versions[0]):
+ while self._versions[0].id < least_kept and self._pruning_policy(
+ self, self._versions[0]
+ ):
self._versions.popleft()
def set_max_versions(self, max_versions: Optional[int]) -> None:
of versions
"""
if max_versions is not None and max_versions < 1:
- raise ValueError('max versions must be at least 1')
+ raise ValueError("max versions must be at least 1")
if max_versions is None:
+
def policy(zone, _): # pylint: disable=unused-argument
return False
+
else:
+
def policy(zone, _):
return len(zone._versions) > max_versions
+
self.set_pruning_policy(policy)
- def set_pruning_policy(self, policy: Optional[Callable[['Zone', Version], Optional[bool]]]) -> None:
+ def set_pruning_policy(
+ self, policy: Optional[Callable[["Zone", Version], Optional[bool]]]
+ ) -> None:
"""Set the pruning policy for the zone.
The *policy* function takes a `Version` and returns `True` if
id = 1
return id
- def find_node(self, name: Union[dns.name.Name, str], create: bool=False) -> dns.node.Node:
+ def find_node(
+ self, name: Union[dns.name.Name, str], create: bool = False
+ ) -> dns.node.Node:
if create:
raise UseTransaction
return super().find_node(name)
def delete_node(self, name: Union[dns.name.Name, str]) -> None:
raise UseTransaction
- def find_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE,
- create: bool=False) -> dns.rdataset.Rdataset:
+ def find_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> dns.rdataset.Rdataset:
if create:
raise UseTransaction
rdataset = super().find_rdataset(name, rdtype, covers)
return dns.rdataset.ImmutableRdataset(rdataset)
- def get_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE,
- create: bool=False) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> Optional[dns.rdataset.Rdataset]:
if create:
raise UseTransaction
rdataset = super().get_rdataset(name, rdtype, covers)
else:
return None
- def delete_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) -> None:
+ def delete_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> None:
raise UseTransaction
- def replace_rdataset(self, name: Union[dns.name.Name, str], replacement: dns.rdataset.Rdataset) -> None:
+ def replace_rdataset(
+ self, name: Union[dns.name.Name, str], replacement: dns.rdataset.Rdataset
+ ) -> None:
raise UseTransaction
import sys
-if sys.platform == 'win32':
+if sys.platform == "win32":
from typing import Any
try:
import threading as _threading
except ImportError: # pragma: no cover
- import dummy_threading as _threading # type: ignore
+ import dummy_threading as _threading # type: ignore
import pythoncom
import wmi
+
_have_wmi = True
except Exception:
_have_wmi = False
# Sometimes DHCP servers add a '.' prefix to the default domain, and
# Windows just stores such values in the registry (see #687).
# Check for this and fix it.
- if domain.startswith('.'):
+ if domain.startswith("."):
domain = domain[1:]
return dns.name.from_text(domain)
self.search = []
if _have_wmi:
+
class _WMIGetter(_threading.Thread):
def __init__(self):
super().__init__()
if interface.IPEnabled:
self.info.domain = _config_domain(interface.DNSDomain)
self.info.nameservers = list(interface.DNSServerSearchOrder)
- self.info.search = [dns.name.from_text(x) for x in
- interface.DNSDomainSuffixSearchOrder]
+ self.info.search = [
+ dns.name.from_text(x)
+ for x in interface.DNSDomainSuffixSearchOrder
+ ]
break
finally:
pythoncom.CoUninitialize()
self.start()
self.join()
return self.info
+
else:
+
class _WMIGetter: # type: ignore
pass
-
class _RegistryGetter:
def __init__(self):
self.info = DnsInfo()
# delimiter in between ' ' and ',' (and vice-versa) in various
# versions of windows.
#
- if entry.find(' ') >= 0:
- split_char = ' '
- elif entry.find(',') >= 0:
- split_char = ','
+ if entry.find(" ") >= 0:
+ split_char = " "
+ elif entry.find(",") >= 0:
+ split_char = ","
else:
# probably a singleton; treat as a space-separated list.
- split_char = ' '
+ split_char = " "
return split_char
def _config_nameservers(self, nameservers):
def _config_fromkey(self, key, always_try_domain):
try:
- servers, _ = winreg.QueryValueEx(key, 'NameServer')
+ servers, _ = winreg.QueryValueEx(key, "NameServer")
except WindowsError:
servers = None
if servers:
self._config_nameservers(servers)
if servers or always_try_domain:
try:
- dom, _ = winreg.QueryValueEx(key, 'Domain')
+ dom, _ = winreg.QueryValueEx(key, "Domain")
if dom:
self.info.domain = _config_domain(dom)
except WindowsError:
pass
else:
try:
- servers, _ = winreg.QueryValueEx(key, 'DhcpNameServer')
+ servers, _ = winreg.QueryValueEx(key, "DhcpNameServer")
except WindowsError:
servers = None
if servers:
self._config_nameservers(servers)
try:
- dom, _ = winreg.QueryValueEx(key, 'DhcpDomain')
+ dom, _ = winreg.QueryValueEx(key, "DhcpDomain")
if dom:
self.info.domain = _config_domain(dom)
except WindowsError:
pass
try:
- search, _ = winreg.QueryValueEx(key, 'SearchList')
+ search, _ = winreg.QueryValueEx(key, "SearchList")
except WindowsError:
search = None
if search is None:
try:
- search, _ = winreg.QueryValueEx(key, 'DhcpSearchList')
+ search, _ = winreg.QueryValueEx(key, "DhcpSearchList")
except WindowsError:
search = None
if search:
# 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)
+ 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')
+ connection_key, "PnpInstanceID"
+ )
if ttype != winreg.REG_SZ:
raise ValueError # pragma: no cover
device_key = winreg.OpenKey(
- lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)
+ lm, r"SYSTEM\CurrentControlSet\Enum\%s" % pnp_id
+ )
try:
# Get ConfigFlags for this device
- (flags, ttype) = winreg.QueryValueEx(
- device_key, 'ConfigFlags')
+ (flags, ttype) = winreg.QueryValueEx(device_key, "ConfigFlags")
if ttype != winreg.REG_DWORD:
raise ValueError # pragma: no cover
lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
try:
- tcp_params = winreg.OpenKey(lm,
- r'SYSTEM\CurrentControlSet'
- r'\Services\Tcpip\Parameters')
+ tcp_params = winreg.OpenKey(
+ lm, r"SYSTEM\CurrentControlSet" r"\Services\Tcpip\Parameters"
+ )
try:
self._config_fromkey(tcp_params, True)
finally:
tcp_params.Close()
- interfaces = winreg.OpenKey(lm,
- r'SYSTEM\CurrentControlSet'
- r'\Services\Tcpip\Parameters'
- r'\Interfaces')
+ interfaces = winreg.OpenKey(
+ lm,
+ r"SYSTEM\CurrentControlSet"
+ r"\Services\Tcpip\Parameters"
+ r"\Interfaces",
+ )
try:
i = 0
while True:
import dns.exception
import dns.name
+
class Parser:
- def __init__(self, wire: bytes, current: int=0):
+ def __init__(self, wire: bytes, current: int = 0):
self.wire = wire
self.current = 0
self.end = len(self.wire)
assert size >= 0
if size > self.remaining():
raise dns.exception.FormError
- output = self.wire[self.current:self.current + size]
+ output = self.wire[self.current : self.current + size]
self.current += size
self.furthest = max(self.furthest, self.current)
return output
- def get_counted_bytes(self, length_size: int=1) -> bytes:
- length = int.from_bytes(self.get_bytes(length_size), 'big')
+ def get_counted_bytes(self, length_size: int = 1) -> bytes:
+ length = int.from_bytes(self.get_bytes(length_size), "big")
return self.get_bytes(length)
def get_remaining(self) -> bytes:
return self.get_bytes(self.remaining())
def get_uint8(self) -> int:
- return struct.unpack('!B', self.get_bytes(1))[0]
+ return struct.unpack("!B", self.get_bytes(1))[0]
def get_uint16(self) -> int:
- return struct.unpack('!H', self.get_bytes(2))[0]
+ return struct.unpack("!H", self.get_bytes(2))[0]
def get_uint32(self) -> int:
- return struct.unpack('!I', self.get_bytes(4))[0]
+ return struct.unpack("!I", self.get_bytes(4))[0]
def get_uint48(self) -> int:
- return int.from_bytes(self.get_bytes(6), 'big')
+ return int.from_bytes(self.get_bytes(6), "big")
def get_struct(self, format: str) -> Tuple:
return struct.unpack(format, self.get_bytes(struct.calcsize(format)))
- def get_name(self, origin: Optional['dns.name.Name']=None) -> 'dns.name.Name':
+ def get_name(self, origin: Optional["dns.name.Name"] = None) -> "dns.name.Name":
name = dns.name.from_wire_parser(self)
if origin:
name = name.relativize(origin)
"""A zone transfer response got a non-zero rcode."""
def __init__(self, rcode):
- message = 'Zone transfer error: %s' % dns.rcode.to_text(rcode)
+ message = "Zone transfer error: %s" % dns.rcode.to_text(rcode)
super().__init__(message)
self.rcode = rcode
State machine for zone transfers.
"""
- def __init__(self, txn_manager: dns.transaction.TransactionManager,
- rdtype: dns.rdatatype.RdataType=dns.rdatatype.AXFR,
- serial: Optional[int]=None, is_udp: bool=False):
+ def __init__(
+ self,
+ txn_manager: dns.transaction.TransactionManager,
+ rdtype: dns.rdatatype.RdataType = dns.rdatatype.AXFR,
+ serial: Optional[int] = None,
+ is_udp: bool = False,
+ ):
"""Initialize an inbound zone transfer.
*txn_manager* is a :py:class:`dns.transaction.TransactionManager`.
self.rdtype = rdtype
if rdtype == dns.rdatatype.IXFR:
if serial is None:
- raise ValueError('a starting serial must be supplied for IXFRs')
+ raise ValueError("a starting serial must be supplied for IXFRs")
elif is_udp:
- raise ValueError('is_udp specified for AXFR')
+ raise ValueError("is_udp specified for AXFR")
self.serial = serial
self.is_udp = is_udp
(_, _, self.origin) = txn_manager.origin_information()
# the origin.
#
if not message.answer or message.answer[0].name != self.origin:
- raise dns.exception.FormError("No answer or RRset not "
- "for zone origin")
+ raise dns.exception.FormError(
+ "No answer or RRset not " "for zone origin"
+ )
rrset = message.answer[0]
rdataset = rrset
if rdataset.rdtype != dns.rdatatype.SOA:
# We're already up-to-date.
#
self.done = True
- elif dns.serial.Serial(self.soa_rdataset[0].serial) < \
- self.serial:
+ elif dns.serial.Serial(self.soa_rdataset[0].serial) < self.serial:
# It went backwards!
raise SerialWentBackwards
else:
if self.done:
raise dns.exception.FormError("answers after final SOA")
assert self.txn is not None # for mypy
- if rdataset.rdtype == dns.rdatatype.SOA and \
- name == self.origin:
+ if rdataset.rdtype == dns.rdatatype.SOA and name == self.origin:
#
# Every time we see an origin SOA delete_mode inverts
#
# check that we're seeing the record in the expected
# part of the response.
#
- if rdataset == self.soa_rdataset and \
- (self.rdtype == dns.rdatatype.AXFR or
- (self.rdtype == dns.rdatatype.IXFR and
- self.delete_mode)):
+ if rdataset == self.soa_rdataset and (
+ self.rdtype == dns.rdatatype.AXFR
+ or (self.rdtype == dns.rdatatype.IXFR and self.delete_mode)
+ ):
#
# This is the final SOA
#
if self.expecting_SOA:
# We got an empty IXFR sequence!
- raise dns.exception.FormError('empty IXFR sequence')
- if self.rdtype == dns.rdatatype.IXFR \
- and self.serial != rdataset[0].serial:
- raise dns.exception.FormError('unexpected end of IXFR '
- 'sequence')
+ raise dns.exception.FormError("empty IXFR sequence")
+ if (
+ self.rdtype == dns.rdatatype.IXFR
+ and self.serial != rdataset[0].serial
+ ):
+ raise dns.exception.FormError(
+ "unexpected end of IXFR " "sequence"
+ )
self.txn.replace(name, rdataset)
self.txn.commit()
self.txn = None
# This is the start of an IXFR deletion set
if rdataset[0].serial != self.serial:
raise dns.exception.FormError(
- "IXFR base serial mismatch")
+ "IXFR base serial mismatch"
+ )
else:
# This is the start of an IXFR addition set
self.serial = rdataset[0].serial
self.txn.replace(name, rdataset)
else:
# We saw a non-final SOA for the origin in an AXFR.
- raise dns.exception.FormError('unexpected origin SOA '
- 'in AXFR')
+ raise dns.exception.FormError(
+ "unexpected origin SOA " "in AXFR"
+ )
continue
if self.expecting_SOA:
#
# This is a UDP IXFR and we didn't get to done, and we didn't
# get the proper "truncated" response
#
- raise dns.exception.FormError('unexpected end of UDP IXFR')
+ raise dns.exception.FormError("unexpected end of UDP IXFR")
return self.done
#
return False
-def make_query(txn_manager: dns.transaction.TransactionManager, serial: Optional[int]=0,
- use_edns: Optional[Union[int, bool]]=None, ednsflags: Optional[int]=None, payload: Optional[int]=None,
- request_payload: Optional[int]=None, options: Optional[List[dns.edns.Option]]=None,
- keyring: Any=None, keyname: Optional[dns.name.Name]=None,
- keyalgorithm: Union[dns.name.Name, str]=dns.tsig.default_algorithm) \
- -> Tuple[dns.message.QueryMessage, Optional[int]]:
+def make_query(
+ txn_manager: dns.transaction.TransactionManager,
+ serial: Optional[int] = 0,
+ use_edns: Optional[Union[int, bool]] = None,
+ ednsflags: Optional[int] = None,
+ payload: Optional[int] = None,
+ request_payload: Optional[int] = None,
+ options: Optional[List[dns.edns.Option]] = None,
+ keyring: Any = None,
+ keyname: Optional[dns.name.Name] = None,
+ keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm,
+) -> Tuple[dns.message.QueryMessage, Optional[int]]:
"""Make an AXFR or IXFR query.
*txn_manager* is a ``dns.transaction.TransactionManager``, typically a
"""
(zone_origin, _, origin) = txn_manager.origin_information()
if zone_origin is None:
- raise ValueError('no zone origin')
+ raise ValueError("no zone origin")
if serial is None:
rdtype = dns.rdatatype.AXFR
elif not isinstance(serial, int):
- raise ValueError('serial is not an integer')
+ raise ValueError("serial is not an integer")
elif serial == 0:
with txn_manager.reader() as txn:
- rdataset = txn.get(origin, 'SOA')
+ rdataset = txn.get(origin, "SOA")
if rdataset:
serial = rdataset[0].serial
rdtype = dns.rdatatype.IXFR
elif serial > 0 and serial < 4294967296:
rdtype = dns.rdatatype.IXFR
else:
- raise ValueError('serial out-of-range')
+ raise ValueError("serial out-of-range")
rdclass = txn_manager.get_class()
- q = dns.message.make_query(zone_origin, rdtype, rdclass,
- use_edns, False, ednsflags, payload,
- request_payload, options)
+ q = dns.message.make_query(
+ zone_origin,
+ rdtype,
+ rdclass,
+ use_edns,
+ False,
+ ednsflags,
+ payload,
+ request_payload,
+ options,
+ )
if serial is not None:
- rdata = dns.rdata.from_text(rdclass, 'SOA', f'. . {serial} 0 0 0 0')
- rrset = q.find_rrset(q.authority, zone_origin, rdclass,
- dns.rdatatype.SOA, create=True)
+ rdata = dns.rdata.from_text(rdclass, "SOA", f". . {serial} 0 0 0 0")
+ rrset = q.find_rrset(
+ q.authority, zone_origin, rdclass, dns.rdatatype.SOA, create=True
+ )
rrset.add(rdata, 0)
if keyring is not None:
q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
return (q, serial)
+
def extract_serial_from_query(query: dns.message.Message) -> Optional[int]:
"""Extract the SOA serial number from query if it is an IXFR and return
it, otherwise return None.
an appropriate SOA RRset in the authority section.
"""
if not isinstance(query, dns.message.QueryMessage):
- raise ValueError('query not a QueryMessage')
+ raise ValueError("query not a QueryMessage")
question = query.question[0]
if question.rdtype == dns.rdatatype.AXFR:
return None
elif question.rdtype != dns.rdatatype.IXFR:
raise ValueError("query is not an AXFR or IXFR")
- soa = query.find_rrset(query.authority, question.name, question.rdclass,
- dns.rdatatype.SOA)
+ soa = query.find_rrset(
+ query.authority, question.name, question.rdclass, dns.rdatatype.SOA
+ )
return soa[0].serial
node_factory = dns.node.Node
- __slots__ = ['rdclass', 'origin', 'nodes', 'relativize']
-
- def __init__(self, origin: Optional[Union[dns.name.Name, str]],
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN, relativize: bool=True):
+ __slots__ = ["rdclass", "origin", "nodes", "relativize"]
+
+ def __init__(
+ self,
+ origin: Optional[Union[dns.name.Name, str]],
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ relativize: bool = True,
+ ):
"""Initialize a zone object.
*origin* is the origin of the zone. It may be a ``dns.name.Name``,
if isinstance(origin, str):
origin = dns.name.from_text(origin)
elif not isinstance(origin, dns.name.Name):
- raise ValueError("origin parameter must be convertible to a "
- "DNS name")
+ raise ValueError(
+ "origin parameter must be convertible to a " "DNS name"
+ )
if not origin.is_absolute():
raise ValueError("origin parameter must be an absolute name")
self.origin = origin
if not isinstance(other, Zone):
return False
- if self.rdclass != other.rdclass or \
- self.origin != other.origin or \
- self.nodes != other.nodes:
+ if (
+ self.rdclass != other.rdclass
+ or self.origin != other.origin
+ or self.nodes != other.nodes
+ ):
return False
return True
# This should probably never happen as other code (e.g.
# _rr_line) will notice the lack of an origin before us, but
# we check just in case!
- raise KeyError('no zone origin is defined')
+ raise KeyError("no zone origin is defined")
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)
elif not self.relativize:
# We have a relative name in a non-relative zone, so derelativize.
if self.origin is None:
- raise KeyError('no zone origin is defined')
+ raise KeyError("no zone origin is defined")
name = name.derelativize(self.origin)
return name
key = self._validate_name(key)
return key in self.nodes
- def find_node(self, name: Union[dns.name.Name, str], create: bool=False) -> dns.node.Node:
+ def find_node(
+ self, name: Union[dns.name.Name, str], create: bool = False
+ ) -> dns.node.Node:
"""Find a node in the zone, possibly creating it.
*name*: the name of the node to find.
self.nodes[name] = node
return node
- def get_node(self, name: Union[dns.name.Name, str], create: bool=False) -> Optional[dns.node.Node]:
+ def get_node(
+ self, name: Union[dns.name.Name, str], create: bool = False
+ ) -> Optional[dns.node.Node]:
"""Get a node in the zone, possibly creating it.
This method is like ``find_node()``, except it returns None instead
if name in self.nodes:
del self.nodes[name]
- def find_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE,
- create: bool=False) -> dns.rdataset.Rdataset:
+ def find_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> dns.rdataset.Rdataset:
"""Look for an rdataset with the specified name and type in the zone,
and return an rdataset encapsulating it.
node = self.find_node(the_name, create)
return node.find_rdataset(self.rdclass, the_rdtype, the_covers, create)
- def get_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE,
- create: bool=False) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> Optional[dns.rdataset.Rdataset]:
"""Look for an rdataset with the specified name and type in the zone.
This method is like ``find_rdataset()``, except it returns None instead
rdataset = None
return rdataset
- def delete_rdataset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) -> None:
+ def delete_rdataset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> None:
"""Delete the rdataset matching *rdtype* and *covers*, if it
exists at the node specified by *name*.
- It is not an error if the node does not exist, or if there is no
- matching rdataset at the node.
+ It is not an error if the node does not exist, or if there is no matching
+ rdataset at the node.
- If the node has no rdatasets after the deletion, it will itself
- be deleted.
+ If the node has no rdatasets after the deletion, it will itself be deleted.
- *name*: the name of the node to find.
- The value may be a ``dns.name.Name`` or a ``str``. If absolute, the
- name must be a subdomain of the zone's origin. If ``zone.relativize``
- is ``True``, then the name will be relativized.
+ *name*: the name of the node to find. The value may be a ``dns.name.Name`` or a
+ ``str``. If absolute, the name must be a subdomain of the zone's origin. If
+ ``zone.relativize`` is ``True``, then the name will be relativized.
*rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdata type desired.
- *covers*, a ``dns.rdatatype.RdataType`` or ``str`` or ``None``, the covered type.
- Usually this value is ``dns.rdatatype.NONE``, but if the
- rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``,
- then the covers value will be the rdata type the SIG/RRSIG
- covers. The library treats the SIG and RRSIG types as if they
- were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).
- This makes RRSIGs much easier to work with than if RRSIGs
- covering different rdata types were aggregated into a single
- RRSIG rdataset.
+ *covers*, a ``dns.rdatatype.RdataType`` or ``str`` or ``None``, the covered
+ type. Usually this value is ``dns.rdatatype.NONE``, but if the rdtype is
+ ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, then the covers value will be
+ the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types
+ as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This
+ makes RRSIGs much easier to work with than if RRSIGs covering different rdata
+ types were aggregated into a single RRSIG rdataset.
"""
the_name = self._validate_name(name)
if len(node) == 0:
self.delete_node(the_name)
- def replace_rdataset(self, name: Union[dns.name.Name, str],
- replacement: dns.rdataset.Rdataset) -> None:
+ def replace_rdataset(
+ self, name: Union[dns.name.Name, str], replacement: dns.rdataset.Rdataset
+ ) -> None:
"""Replace an rdataset at name.
It is not an error if there is no rdataset matching I{replacement}.
"""
if replacement.rdclass != self.rdclass:
- raise ValueError('replacement.rdclass != zone.rdclass')
+ raise ValueError("replacement.rdclass != zone.rdclass")
node = self.find_node(name, True)
node.replace_rdataset(replacement)
- def find_rrset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) -> dns.rrset.RRset:
+ def find_rrset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> dns.rrset.RRset:
"""Look for an rdataset with the specified name and type in the zone,
and return an RRset encapsulating it.
rrset.update(rdataset)
return rrset
- def get_rrset(self, name: Union[dns.name.Name, str],
- rdtype: Union[dns.rdatatype.RdataType, str],
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) -> Optional[dns.rrset.RRset]:
+ def get_rrset(
+ self,
+ name: Union[dns.name.Name, str],
+ rdtype: Union[dns.rdatatype.RdataType, str],
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> Optional[dns.rrset.RRset]:
"""Look for an rdataset with the specified name and type in the zone,
and return an RRset encapsulating it.
rrset = None
return rrset
- def iterate_rdatasets(self, rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.ANY,
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) \
- -> Iterator[Tuple[dns.name.Name, dns.rdataset.Rdataset]]:
+ def iterate_rdatasets(
+ self,
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.ANY,
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> Iterator[Tuple[dns.name.Name, dns.rdataset.Rdataset]]:
"""Return a generator which yields (name, rdataset) tuples for
all rdatasets in the zone which have the specified *rdtype*
and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default,
covers = dns.rdatatype.RdataType.make(covers)
for (name, node) in self.items():
for rds in node:
- if rdtype == dns.rdatatype.ANY or \
- (rds.rdtype == rdtype and rds.covers == covers):
+ if rdtype == dns.rdatatype.ANY or (
+ rds.rdtype == rdtype and rds.covers == covers
+ ):
yield (name, rds)
- def iterate_rdatas(self, rdtype: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.ANY,
- covers: Union[dns.rdatatype.RdataType, str]=dns.rdatatype.NONE) \
- -> Iterator[Tuple[dns.name.Name, int, dns.rdata.Rdata]]:
+ def iterate_rdatas(
+ self,
+ rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.ANY,
+ covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE,
+ ) -> Iterator[Tuple[dns.name.Name, int, dns.rdata.Rdata]]:
"""Return a generator which yields (name, ttl, rdata) tuples for
all rdatas in the zone which have the specified *rdtype*
and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default,
covers = dns.rdatatype.RdataType.make(covers)
for (name, node) in self.items():
for rds in node:
- if rdtype == dns.rdatatype.ANY or \
- (rds.rdtype == rdtype and rds.covers == covers):
+ if rdtype == dns.rdatatype.ANY or (
+ rds.rdtype == rdtype and rds.covers == covers
+ ):
for rdata in rds:
yield (name, rds.ttl, rdata)
- def to_file(self, f: Any, sorted: bool=True, relativize: bool=True, nl: Optional[str]=None,
- want_comments: bool=False, want_origin: bool=False) -> None:
+ def to_file(
+ self,
+ f: Any,
+ sorted: bool = True,
+ relativize: bool = True,
+ nl: Optional[str] = None,
+ want_comments: bool = False,
+ want_origin: bool = False,
+ ) -> None:
"""Write a zone to a file.
*f*, a file or `str`. If *f* is a string, it is treated
with contextlib.ExitStack() as stack:
if isinstance(f, str):
- f = stack.enter_context(open(f, 'wb'))
+ f = stack.enter_context(open(f, "wb"))
# must be in this way, f.encoding may contain None, or even
# attribute may not be there
- file_enc = getattr(f, 'encoding', None)
+ file_enc = getattr(f, "encoding", None)
if file_enc is None:
- file_enc = 'utf-8'
+ file_enc = "utf-8"
if nl is None:
# binary mode, '\n' is not enough
nl_b = os.linesep.encode(file_enc)
- nl = '\n'
+ nl = "\n"
elif isinstance(nl, str):
nl_b = nl.encode(file_enc)
else:
if want_origin:
assert self.origin is not None
- l = '$ORIGIN ' + self.origin.to_text()
+ l = "$ORIGIN " + self.origin.to_text()
l_b = l.encode(file_enc)
try:
f.write(l_b)
else:
names = self.keys()
for n in names:
- l = self[n].to_text(n, origin=self.origin,
- relativize=relativize,
- want_comments=want_comments)
+ l = self[n].to_text(
+ n,
+ origin=self.origin,
+ relativize=relativize,
+ want_comments=want_comments,
+ )
l_b = l.encode(file_enc)
try:
f.write(l)
f.write(nl)
- def to_text(self, sorted: bool=True, relativize: bool=True, nl: Optional[str]=None,
- want_comments: bool=False, want_origin: bool=False) -> str:
+ def to_text(
+ self,
+ sorted: bool = True,
+ relativize: bool = True,
+ nl: Optional[str] = None,
+ want_comments: bool = False,
+ want_origin: bool = False,
+ ) -> str:
"""Return a zone's text as though it were written to a file.
*sorted*, a ``bool``. If True, the default, then the file
Returns a ``str``.
"""
temp_buffer = io.StringIO()
- self.to_file(temp_buffer, sorted, relativize, nl, want_comments,
- want_origin)
+ self.to_file(temp_buffer, sorted, relativize, nl, want_comments, want_origin)
return_value = temp_buffer.getvalue()
temp_buffer.close()
return return_value
if self.get_rdataset(name, dns.rdatatype.NS) is None:
raise NoNS
- def get_soa(self, txn: Optional[dns.transaction.Transaction]=None) -> dns.rdtypes.ANY.SOA.SOA:
+ def get_soa(
+ self, txn: Optional[dns.transaction.Transaction] = None
+ ) -> dns.rdtypes.ANY.SOA.SOA:
"""Get the zone SOA rdata.
Raises ``dns.zone.NoSOA`` if there is no SOA RRset.
raise NoSOA
return soa[0]
- def _compute_digest(self, hash_algorithm: DigestHashAlgorithm, scheme: DigestScheme=DigestScheme.SIMPLE) -> bytes:
+ def _compute_digest(
+ self,
+ hash_algorithm: DigestHashAlgorithm,
+ scheme: DigestScheme = DigestScheme.SIMPLE,
+ ) -> bytes:
hashinfo = _digest_hashers.get(hash_algorithm)
if not hashinfo:
raise UnsupportedDigestHashAlgorithm
hasher = hashinfo()
for (name, node) in sorted(self.items()):
rrnamebuf = name.to_digestable(self.origin)
- for rdataset in sorted(node,
- key=lambda rds: (rds.rdtype, rds.covers)):
- if name == origin_name and \
- dns.rdatatype.ZONEMD in (rdataset.rdtype, rdataset.covers):
+ for rdataset in sorted(node, key=lambda rds: (rds.rdtype, rds.covers)):
+ if name == origin_name and dns.rdatatype.ZONEMD in (
+ rdataset.rdtype,
+ rdataset.covers,
+ ):
continue
- rrfixed = struct.pack('!HHI', rdataset.rdtype,
- rdataset.rdclass, rdataset.ttl)
- rdatas = [rdata.to_digestable(self.origin)
- for rdata in rdataset]
+ rrfixed = struct.pack(
+ "!HHI", rdataset.rdtype, rdataset.rdclass, rdataset.ttl
+ )
+ rdatas = [rdata.to_digestable(self.origin) for rdata in rdataset]
for rdata in sorted(rdatas):
- rrlen = struct.pack('!H', len(rdata))
+ rrlen = struct.pack("!H", len(rdata))
hasher.update(rrnamebuf + rrfixed + rrlen + rdata)
return hasher.digest()
- def compute_digest(self, hash_algorithm: DigestHashAlgorithm,
- scheme: DigestScheme=DigestScheme.SIMPLE) -> dns.rdtypes.ANY.ZONEMD.ZONEMD:
+ def compute_digest(
+ self,
+ hash_algorithm: DigestHashAlgorithm,
+ scheme: DigestScheme = DigestScheme.SIMPLE,
+ ) -> dns.rdtypes.ANY.ZONEMD.ZONEMD:
serial = self.get_soa().serial
digest = self._compute_digest(hash_algorithm, scheme)
- return dns.rdtypes.ANY.ZONEMD.ZONEMD(self.rdclass,
- dns.rdatatype.ZONEMD,
- serial, scheme, hash_algorithm,
- digest)
+ return dns.rdtypes.ANY.ZONEMD.ZONEMD(
+ self.rdclass, dns.rdatatype.ZONEMD, serial, scheme, hash_algorithm, digest
+ )
- def verify_digest(self, zonemd: Optional[dns.rdtypes.ANY.ZONEMD.ZONEMD]=None) -> None:
+ def verify_digest(
+ self, zonemd: Optional[dns.rdtypes.ANY.ZONEMD.ZONEMD] = None
+ ) -> None:
digests: Union[dns.rdataset.Rdataset, List[dns.rdtypes.ANY.ZONEMD.ZONEMD]]
if zonemd:
digests = [zonemd]
digests = rds
for digest in digests:
try:
- computed = self._compute_digest(digest.hash_algorithm,
- digest.scheme)
+ computed = self._compute_digest(digest.hash_algorithm, digest.scheme)
if computed == digest.digest:
return
except Exception:
# TransactionManager methods
- def reader(self) -> 'Transaction':
- return Transaction(self, False,
- Version(self, 1, self.nodes, self.origin))
+ def reader(self) -> "Transaction":
+ return Transaction(self, False, Version(self, 1, self.nodes, self.origin))
- def writer(self, replacement: bool=False) -> 'Transaction':
+ def writer(self, replacement: bool = False) -> "Transaction":
txn = Transaction(self, replacement)
txn._setup_version()
return txn
- def origin_information(self) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]:
+ def origin_information(
+ self,
+ ) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]:
effective: Optional[dns.name.Name]
if self.relativize:
effective = dns.name.empty
# A node with a version id.
+
class VersionedNode(dns.node.Node): # lgtm[py/missing-equals]
- __slots__ = ['id']
+ __slots__ = ["id"]
def __init__(self):
super().__init__()
@dns.immutable.immutable
class ImmutableVersionedNode(VersionedNode):
- __slots__ = ['id']
+ __slots__ = ["id"]
def __init__(self, node):
super().__init__()
[dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets]
)
- def find_rdataset(self, rdclass: dns.rdataclass.RdataClass, rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> dns.rdataset.Rdataset:
+ def find_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> dns.rdataset.Rdataset:
if create:
raise TypeError("immutable")
return super().find_rdataset(rdclass, rdtype, covers, False)
- def get_rdataset(self, rdclass: dns.rdataclass.RdataClass, rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE,
- create: bool=False) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ create: bool = False,
+ ) -> Optional[dns.rdataset.Rdataset]:
if create:
raise TypeError("immutable")
return super().get_rdataset(rdclass, rdtype, covers, False)
- def delete_rdataset(self, rdclass: dns.rdataclass.RdataClass, rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType=dns.rdatatype.NONE) -> None:
+ def delete_rdataset(
+ self,
+ rdclass: dns.rdataclass.RdataClass,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
+ ) -> None:
raise TypeError("immutable")
def replace_rdataset(self, replacement: dns.rdataset.Rdataset) -> None:
class Version:
- def __init__(self, zone: Zone, id: int,
- nodes: Optional[Dict[dns.name.Name, dns.node.Node]]=None,
- origin: Optional[dns.name.Name]=None):
+ def __init__(
+ self,
+ zone: Zone,
+ id: int,
+ nodes: Optional[Dict[dns.name.Name, dns.node.Node]] = None,
+ origin: Optional[dns.name.Name] = None,
+ ):
self.zone = zone
self.id = id
if nodes is not None:
# This should probably never happen as other code (e.g.
# _rr_line) will notice the lack of an origin before us, but
# we check just in case!
- raise KeyError('no zone origin is defined')
+ raise KeyError("no zone origin is defined")
if not name.is_subdomain(self.origin):
raise KeyError("name is not a subdomain of the zone origin")
if self.zone.relativize:
elif not self.zone.relativize:
# We have a relative name in a non-relative zone, so derelativize.
if self.origin is None:
- raise KeyError('no zone origin is defined')
+ raise KeyError("no zone origin is defined")
name = name.derelativize(self.origin)
return name
name = self._validate_name(name)
return self.nodes.get(name)
- def get_rdataset(self, name: dns.name.Name, rdtype: dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType) -> Optional[dns.rdataset.Rdataset]:
+ def get_rdataset(
+ self,
+ name: dns.name.Name,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType,
+ ) -> Optional[dns.rdataset.Rdataset]:
node = self.get_node(name)
if node is None:
return None
class WritableVersion(Version):
- def __init__(self, zone: Zone, replacement: bool=False):
+ def __init__(self, zone: Zone, replacement: bool = False):
# The zone._versions_lock must be held by our caller in a versioned
# zone.
id = zone._get_next_version_id()
node = self.nodes.get(name)
if node is None or name not in self.changed:
new_node = self.zone.node_factory()
- if hasattr(new_node, 'id'):
+ if hasattr(new_node, "id"):
# We keep doing this for backwards compatibility, as earlier
# code used new_node.id != self.id for the "do we need to CoW?"
# test. Now we use the changed set as this works with both
# regular zones and versioned zones.
#
# We ignore the mypy error as this is safe but it doesn't see it.
- new_node.id = self.id # type: ignore
+ new_node.id = self.id # type: ignore
if node is not None:
# moo! copy on write!
new_node.rdatasets.extend(node.rdatasets)
del self.nodes[name]
self.changed.add(name)
- def put_rdataset(self, name: dns.name.Name, rdataset: dns.rdataset.Rdataset) -> None:
+ def put_rdataset(
+ self, name: dns.name.Name, rdataset: dns.rdataset.Rdataset
+ ) -> None:
node = self._maybe_cow(name)
node.replace_rdataset(rdataset)
- def delete_rdataset(self, name: dns.name.Name, rdtype:dns.rdatatype.RdataType,
- covers: dns.rdatatype.RdataType) -> None:
+ def delete_rdataset(
+ self,
+ name: dns.name.Name,
+ rdtype: dns.rdatatype.RdataType,
+ covers: dns.rdatatype.RdataType,
+ ) -> None:
node = self._maybe_cow(name)
node.delete_rdataset(self.zone.rdclass, rdtype, covers)
if len(node) == 0:
class Transaction(dns.transaction.Transaction):
-
def __init__(self, zone, replacement, version=None, make_immutable=False):
read_only = version is not None
super().__init__(zone, replacement, read_only)
return (absolute, relativize, effective)
-def from_text(text: str, origin: Optional[Union[dns.name.Name, str]]=None,
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN,
- relativize: bool=True, zone_factory: Any=Zone, filename: Optional[str]=None,
- allow_include: bool=False, check_origin: bool=True,
- idna_codec: Optional[dns.name.IDNACodec]=None) -> Zone:
+def from_text(
+ text: str,
+ origin: Optional[Union[dns.name.Name, str]] = None,
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ relativize: bool = True,
+ zone_factory: Any = Zone,
+ filename: Optional[str] = None,
+ allow_include: bool = False,
+ check_origin: bool = True,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+) -> Zone:
"""Build a zone object from a zone file format string.
*text*, a ``str``, the zone file format input.
of the zone; if not specified, the first ``$ORIGIN`` statement in the
zone file will determine the origin of the zone.
- *rdclass*, a ``dns.rdataclass.RdataClass``, the zone's rdata class; the default is class IN.
+ *rdclass*, a ``dns.rdataclass.RdataClass``, the zone's rdata class; the default is
+ class IN.
*relativize*, a ``bool``, determine's whether domain names are
relativized to the zone's origin. The default is ``True``.
# interface is from_file().
if filename is None:
- filename = '<string>'
+ filename = "<string>"
zone = zone_factory(origin, rdclass, relativize=relativize)
with zone.writer(True) as txn:
tok = dns.tokenizer.Tokenizer(text, filename, idna_codec=idna_codec)
- reader = dns.zonefile.Reader(tok, rdclass, txn,
- allow_include=allow_include)
+ reader = dns.zonefile.Reader(tok, rdclass, txn, allow_include=allow_include)
try:
reader.read()
except dns.zonefile.UnknownOrigin:
return zone
-def from_file(f: Any, origin: Optional[Union[dns.name.Name, str]]=None,
- rdclass: dns.rdataclass.RdataClass=dns.rdataclass.IN,
- relativize: bool=True, zone_factory: Any=Zone, filename: Optional[str]=None,
- allow_include: bool=True, check_origin: bool=True) -> Zone:
+def from_file(
+ f: Any,
+ origin: Optional[Union[dns.name.Name, str]] = None,
+ rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN,
+ relativize: bool = True,
+ zone_factory: Any = Zone,
+ filename: Optional[str] = None,
+ allow_include: bool = True,
+ check_origin: bool = True,
+) -> Zone:
"""Read a zone file and build a zone object.
*f*, a file or ``str``. If *f* is a string, it is treated
if filename is None:
filename = f
f = stack.enter_context(open(f))
- return from_text(f, origin, rdclass, relativize, zone_factory,
- filename, allow_include, check_origin)
+ return from_text(
+ f,
+ origin,
+ rdclass,
+ relativize,
+ zone_factory,
+ filename,
+ allow_include,
+ check_origin,
+ )
assert False # make mypy happy lgtm[py/unreachable-statement]
-def from_xfr(xfr: Any, zone_factory: Any=Zone, relativize: bool=True, check_origin: bool=True) -> Zone:
+def from_xfr(
+ xfr: Any,
+ zone_factory: Any = Zone,
+ relativize: bool = True,
+ check_origin: bool = True,
+) -> Zone:
"""Convert the output of a zone transfer generator into a zone object.
*xfr*, a generator of ``dns.message.Message`` objects, typically
if not znode:
znode = z.node_factory()
z.nodes[rrset.name] = znode
- zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype,
- rrset.covers, True)
+ zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype, rrset.covers, True)
zrds.update_ttl(rrset.ttl)
for rd in rrset:
zrds.add(rd)
if z is None:
- raise ValueError('empty transfer')
+ raise ValueError("empty transfer")
if check_origin:
z.check_origin()
return z
# empty nodes are neutral.
return
node_kind = node.classify()
- if node_kind == dns.node.NodeKind.CNAME and \
- rdataset_kind == dns.node.NodeKind.REGULAR:
- raise CNAMEAndOtherData('rdataset type is not compatible with a '
- 'CNAME node')
- elif node_kind == dns.node.NodeKind.REGULAR and \
- rdataset_kind == dns.node.NodeKind.CNAME:
- raise CNAMEAndOtherData('CNAME rdataset is not compatible with a '
- 'regular data node')
+ if (
+ node_kind == dns.node.NodeKind.CNAME
+ and rdataset_kind == dns.node.NodeKind.REGULAR
+ ):
+ raise CNAMEAndOtherData("rdataset type is not compatible with a " "CNAME node")
+ elif (
+ node_kind == dns.node.NodeKind.REGULAR
+ and rdataset_kind == dns.node.NodeKind.CNAME
+ ):
+ raise CNAMEAndOtherData(
+ "CNAME rdataset is not compatible with a " "regular data node"
+ )
# Otherwise at least one of the node and the rdataset is neutral, so
# adding the rdataset is ok
-SavedStateType = Tuple[dns.tokenizer.Tokenizer,
- Optional[dns.name.Name], # current_origin
- Optional[dns.name.Name], # last_name
- Optional[Any], # current_file
- int, # last_ttl
- bool, # last_ttl_known
- int, # default_ttl
- bool] # default_ttl_known
+SavedStateType = Tuple[
+ dns.tokenizer.Tokenizer,
+ Optional[dns.name.Name], # current_origin
+ Optional[dns.name.Name], # last_name
+ Optional[Any], # current_file
+ int, # last_ttl
+ bool, # last_ttl_known
+ int, # default_ttl
+ bool,
+] # default_ttl_known
class Reader:
"""Read a DNS zone file into a transaction."""
- def __init__(self, tok: dns.tokenizer.Tokenizer, rdclass: dns.rdataclass.RdataClass,
- txn: dns.transaction.Transaction, allow_include: bool=False,
- allow_directives: bool=True, force_name: Optional[dns.name.Name]=None,
- force_ttl: Optional[int]=None,
- force_rdclass: Optional[dns.rdataclass.RdataClass]=None,
- force_rdtype: Optional[dns.rdatatype.RdataType]=None,
- default_ttl: Optional[int]=None):
+ def __init__(
+ self,
+ tok: dns.tokenizer.Tokenizer,
+ rdclass: dns.rdataclass.RdataClass,
+ txn: dns.transaction.Transaction,
+ allow_include: bool = False,
+ allow_directives: bool = True,
+ force_name: Optional[dns.name.Name] = None,
+ force_ttl: Optional[int] = None,
+ force_rdclass: Optional[dns.rdataclass.RdataClass] = None,
+ force_rdtype: Optional[dns.rdatatype.RdataType] = None,
+ default_ttl: Optional[int] = None,
+ ):
self.tok = tok
- (self.zone_origin, self.relativize, _) = \
- txn.manager.origin_information()
+ (self.zone_origin, self.relativize, _) = txn.manager.origin_information()
self.current_origin = self.zone_origin
self.last_ttl = 0
self.last_ttl_known = False
try:
rdtype = dns.rdatatype.from_text(token.value)
except Exception:
- raise dns.exception.SyntaxError(
- "unknown rdatatype '%s'" % token.value)
+ raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
try:
- rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
- self.current_origin, self.relativize,
- self.zone_origin)
+ rd = dns.rdata.from_text(
+ rdclass,
+ rdtype,
+ self.tok,
+ self.current_origin,
+ self.relativize,
+ self.zone_origin,
+ )
except dns.exception.SyntaxError:
# Catch and reraise.
raise
# helpful filename:line info.
(ty, va) = sys.exc_info()[:2]
raise dns.exception.SyntaxError(
- "caught exception {}: {}".format(str(ty), str(va)))
+ "caught exception {}: {}".format(str(ty), str(va))
+ )
if not self.default_ttl_known and rdtype == dns.rdatatype.SOA:
# The pre-RFC2308 and pre-BIND9 behavior inherits the zone default
g1 = is_generate1.match(side)
if g1:
mod, sign, offset, width, base = g1.groups()
- if sign == '':
- sign = '+'
+ if sign == "":
+ sign = "+"
g2 = is_generate2.match(side)
if g2:
mod, sign, offset = g2.groups()
- if sign == '':
- sign = '+'
+ if sign == "":
+ sign = "+"
width = 0
- base = 'd'
+ base = "d"
g3 = is_generate3.match(side)
if g3:
mod, sign, offset, width = g3.groups()
- if sign == '':
- sign = '+'
- base = 'd'
+ if sign == "":
+ sign = "+"
+ base = "d"
if not (g1 or g2 or g3):
- mod = ''
- sign = '+'
+ mod = ""
+ sign = "+"
offset = 0
width = 0
- base = 'd'
+ base = "d"
- if base != 'd':
+ if base != "d":
raise NotImplementedError()
return mod, sign, offset, width, base
if not token.is_identifier():
raise dns.exception.SyntaxError
except Exception:
- raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
- token.value)
+ raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
# rhs (required)
rhs = token.value
for i in range(start, stop + 1, step):
# +1 because bind is inclusive and python is exclusive
- if lsign == '+':
+ if lsign == "+":
lindex = i + int(loffset)
- elif lsign == '-':
+ elif lsign == "-":
lindex = i - int(loffset)
- if rsign == '-':
+ if rsign == "-":
rindex = i - int(roffset)
- elif rsign == '+':
+ elif rsign == "+":
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("$%s" % (lmod), lzfindex)
+ rdata = rhs.replace("$%s" % (rmod), rzfindex)
- self.last_name = dns.name.from_text(name, self.current_origin,
- self.tok.idna_codec)
+ self.last_name = dns.name.from_text(
+ name, self.current_origin, self.tok.idna_codec
+ )
name = self.last_name
if not name.is_subdomain(self.zone_origin):
self._eat_line()
name = name.relativize(self.zone_origin)
try:
- rd = dns.rdata.from_text(rdclass, rdtype, rdata,
- self.current_origin, self.relativize,
- self.zone_origin)
+ rd = dns.rdata.from_text(
+ rdclass,
+ rdtype,
+ rdata,
+ self.current_origin,
+ self.relativize,
+ self.zone_origin,
+ )
except dns.exception.SyntaxError:
# Catch and reraise.
raise
# 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))
+ )
self.txn.add(name, ttl, rd)
if self.current_file is not None:
self.current_file.close()
if len(self.saved_state) > 0:
- (self.tok,
- self.current_origin,
- self.last_name,
- self.current_file,
- self.last_ttl,
- self.last_ttl_known,
- self.default_ttl,
- self.default_ttl_known) = self.saved_state.pop(-1)
+ (
+ self.tok,
+ self.current_origin,
+ self.last_name,
+ self.current_file,
+ self.last_ttl,
+ self.last_ttl_known,
+ self.default_ttl,
+ self.default_ttl_known,
+ ) = self.saved_state.pop(-1)
continue
break
elif token.is_eol():
elif token.is_comment():
self.tok.get_eol()
continue
- elif token.value[0] == '$' and self.allow_directives:
+ elif token.value[0] == "$" and self.allow_directives:
c = token.value.upper()
- if c == '$TTL':
+ if c == "$TTL":
token = self.tok.get()
if not token.is_identifier():
raise dns.exception.SyntaxError("bad $TTL")
self.default_ttl = dns.ttl.from_text(token.value)
self.default_ttl_known = True
self.tok.get_eol()
- elif c == '$ORIGIN':
+ elif c == "$ORIGIN":
self.current_origin = self.tok.get_name()
self.tok.get_eol()
if self.zone_origin is None:
self.zone_origin = self.current_origin
self.txn._set_origin(self.current_origin)
- elif c == '$INCLUDE' and self.allow_include:
+ elif c == "$INCLUDE" and self.allow_include:
token = self.tok.get()
filename = token.value
token = self.tok.get()
new_origin: Optional[dns.name.Name]
if token.is_identifier():
- new_origin = dns.name.from_text(token.value, self.current_origin, self.tok.idna_codec)
+ new_origin = dns.name.from_text(
+ token.value, self.current_origin, self.tok.idna_codec
+ )
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,
- self.current_origin,
- self.last_name,
- self.current_file,
- self.last_ttl,
- self.last_ttl_known,
- self.default_ttl,
- self.default_ttl_known))
- self.current_file = open(filename, 'r')
- self.tok = dns.tokenizer.Tokenizer(self.current_file,
- filename)
+ self.saved_state.append(
+ (
+ self.tok,
+ self.current_origin,
+ self.last_name,
+ self.current_file,
+ self.last_ttl,
+ self.last_ttl_known,
+ self.default_ttl,
+ self.default_ttl_known,
+ )
+ )
+ self.current_file = open(filename, "r")
+ self.tok = dns.tokenizer.Tokenizer(self.current_file, filename)
self.current_origin = new_origin
- elif c == '$GENERATE':
+ elif c == "$GENERATE":
self._generate_line()
else:
raise dns.exception.SyntaxError(
- "Unknown zone file directive '" + c + "'")
+ "Unknown zone file directive '" + c + "'"
+ )
continue
self.tok.unget(token)
self._rr_line()
if detail is None:
detail = "syntax error"
ex = dns.exception.SyntaxError(
- "%s:%d: %s" % (filename, line_number, detail))
+ "%s:%d: %s" % (filename, line_number, detail)
+ )
tb = sys.exc_info()[2]
raise ex.with_traceback(tb) from None
class RRsetsReaderTransaction(dns.transaction.Transaction):
-
def __init__(self, manager, replacement, read_only):
assert not read_only
super().__init__(manager, replacement, read_only)
if commit and self._changed():
rrsets = []
for (name, _, _), rdataset in self.rdatasets.items():
- rrset = dns.rrset.RRset(name, rdataset.rdclass, rdataset.rdtype,
- rdataset.covers)
+ rrset = dns.rrset.RRset(
+ name, rdataset.rdclass, rdataset.rdtype, rdataset.covers
+ )
rrset.update(rdataset)
rrsets.append(rrset)
self.manager.set_rrsets(rrsets)
class RRSetsReaderManager(dns.transaction.TransactionManager):
- def __init__(self, origin=dns.name.root, relativize=False,
- rdclass=dns.rdataclass.IN):
+ def __init__(
+ self, origin=dns.name.root, relativize=False, rdclass=dns.rdataclass.IN
+ ):
self.origin = origin
self.relativize = relativize
self.rdclass = rdclass
self.rrsets = rrsets
-def read_rrsets(text: Any,
- name: Optional[Union[dns.name.Name, str]]=None,
- ttl: Optional[int]=None,
- rdclass: Optional[Union[dns.rdataclass.RdataClass, str]]=dns.rdataclass.IN,
- default_rdclass: Union[dns.rdataclass.RdataClass, str]=dns.rdataclass.IN,
- rdtype: Optional[Union[dns.rdatatype.RdataType, str]]=None,
- default_ttl: Optional[Union[int, str]]=None,
- idna_codec: Optional[dns.name.IDNACodec]=None,
- origin: Optional[Union[dns.name.Name, str]]=dns.name.root,
- relativize: bool=False) -> List[dns.rrset.RRset]:
+def read_rrsets(
+ text: Any,
+ name: Optional[Union[dns.name.Name, str]] = None,
+ ttl: Optional[int] = None,
+ rdclass: Optional[Union[dns.rdataclass.RdataClass, str]] = dns.rdataclass.IN,
+ default_rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN,
+ rdtype: Optional[Union[dns.rdatatype.RdataType, str]] = None,
+ default_ttl: Optional[Union[int, str]] = None,
+ idna_codec: Optional[dns.name.IDNACodec] = None,
+ origin: Optional[Union[dns.name.Name, str]] = dns.name.root,
+ relativize: bool = False,
+) -> List[dns.rrset.RRset]:
"""Read one or more rrsets from the specified text, possibly subject
to restrictions.
the_rdtype = None
manager = RRSetsReaderManager(origin, relativize, default_rdclass)
with manager.writer(True) as txn:
- tok = dns.tokenizer.Tokenizer(text, '<input>', idna_codec=idna_codec)
- reader = Reader(tok, the_default_rdclass, txn, allow_directives=False,
- force_name=name, force_ttl=ttl, force_rdclass=the_rdclass,
- force_rdtype=the_rdtype, default_ttl=default_ttl)
+ tok = dns.tokenizer.Tokenizer(text, "<input>", idna_codec=idna_codec)
+ reader = Reader(
+ tok,
+ the_default_rdclass,
+ txn,
+ allow_directives=False,
+ force_name=name,
+ force_ttl=ttl,
+ force_rdclass=the_rdclass,
+ force_rdtype=the_rdtype,
+ default_ttl=default_ttl,
+ )
reader.read()
return manager.rrsets
#
import os
import sys
-sys.path.insert(0, os.path.abspath('..'))
+
+sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- 'sphinx.ext.autodoc',
- 'sphinx.ext.viewcode',
- 'sphinx.ext.githubpages',
- 'sphinx.ext.todo'
- ]
+ "sphinx.ext.autodoc",
+ "sphinx.ext.viewcode",
+ "sphinx.ext.githubpages",
+ "sphinx.ext.todo",
+]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = 'dnspython'
-copyright = 'Dnspython Contributors'
-author = 'Dnspython Contributors'
+project = "dnspython"
+copyright = "Dnspython Contributors"
+author = "Dnspython Contributors"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '2.3'
+version = "2.3"
# The full version, including alpha/beta/rc tags.
-release = '2.3.0'
+release = "2.3.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for autodoc --------------------------------------------------
-autoclass_content = 'both'
+autoclass_content = "both"
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-#html_theme = 'alabaster'
+# html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
-htmlhelp_basename = 'dnspythondoc'
+htmlhelp_basename = "dnspythondoc"
# -- Options for LaTeX output ---------------------------------------------
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'dnspython.tex', 'dnspython Documentation',
- 'Nominum, Inc.', 'manual'),
+ (master_doc, "dnspython.tex", "dnspython Documentation", "Nominum, Inc.", "manual"),
]
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'dnspython', 'dnspython Documentation',
- [author], 1)
-]
+man_pages = [(master_doc, "dnspython", "dnspython Documentation", [author], 1)]
# -- Options for Texinfo output -------------------------------------------
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'dnspython', 'dnspython Documentation',
- author, 'dnspython', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ "dnspython",
+ "dnspython Documentation",
+ author,
+ "dnspython",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
title = sys.argv[2]
print(title)
-print('=' * len(title))
+print("=" * len(title))
print()
module = importlib.import_module(name)
for t in sorted(module._by_text.keys()):
- print('.. py:data:: {}.{}'.format(name, t))
- print(' :annotation: = {}'.format(module._by_text[t]))
+ print(".. py:data:: {}.{}".format(name, t))
+ print(" :annotation: = {}".format(module._by_text[t]))
-
import sys
import trio
import dns.asyncquery
import dns.asyncresolver
+
async def main():
if len(sys.argv) > 1:
host = sys.argv[0]
else:
- host = 'www.dnspython.org'
- q = dns.message.make_query(host, 'A')
- r = await dns.asyncquery.udp(q, '8.8.8.8')
+ host = "www.dnspython.org"
+ q = dns.message.make_query(host, "A")
+ r = await dns.asyncquery.udp(q, "8.8.8.8")
print(r)
- q = dns.message.make_query(host, 'A')
- r = await dns.asyncquery.tcp(q, '8.8.8.8')
+ q = dns.message.make_query(host, "A")
+ r = await dns.asyncquery.tcp(q, "8.8.8.8")
print(r)
- q = dns.message.make_query(host, 'A')
- r = await dns.asyncquery.tls(q, '8.8.8.8')
+ q = dns.message.make_query(host, "A")
+ r = await dns.asyncquery.tls(q, "8.8.8.8")
print(r)
- a = await dns.asyncresolver.resolve(host, 'A')
+ a = await dns.asyncresolver.resolve(host, "A")
print(a.response)
zn = await dns.asyncresolver.zone_for_name(host)
print(zn)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
trio.run(main)
# Replace the keyname and secret with appropriate values for your
# configuration.
#
-keyring = dns.tsigkeyring.from_text({
- 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
- })
+keyring = dns.tsigkeyring.from_text({"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="})
#
# Replace "example." with your domain, and "host" with your hostname.
#
-update = dns.update.Update('example.', keyring=keyring)
-update.replace('host', 300, 'A', sys.argv[1])
+update = dns.update.Update("example.", keyring=keyring)
+update.replace("host", 300, "A", sys.argv[1])
#
# Replace "10.0.0.1" with the IP address of your master server.
#
-response = dns.query.tcp(update, '10.0.0.1', timeout=10)
+response = dns.query.tcp(update, "10.0.0.1", timeout=10)
# "simple" below means "simple python data types", i.e. things made of
# combinations of dictionaries, lists, strings, and numbers.
+
def make_rr(simple, rdata):
csimple = copy.copy(simple)
- csimple['data'] = rdata.to_text()
+ csimple["data"] = rdata.to_text()
return csimple
+
def flatten_rrset(rrs):
simple = {
- 'name': str(rrs.name),
- 'type': rrs.rdtype,
+ "name": str(rrs.name),
+ "type": rrs.rdtype,
}
if len(rrs) > 0:
- simple['TTL'] = rrs.ttl
+ simple["TTL"] = rrs.ttl
return [make_rr(simple, rdata) for rdata in rrs]
else:
return [simple]
+
def to_doh_simple(message):
- simple = {
- 'Status': message.rcode()
- }
+ simple = {"Status": message.rcode()}
for f in dns.flags.Flag:
if f != dns.flags.Flag.AA and f != dns.flags.Flag.QR:
# DoH JSON doesn't need AA and omits it. DoH JSON is only
# we don't encode the ecs_client_subnet field
return simple
+
def from_doh_simple(simple, add_qr=False):
message = dns.message.QueryMessage()
flags = 0
if add_qr: # QR is implied
flags |= dns.flags.QR
message.flags = flags
- message.set_rcode(simple.get('Status', 0))
+ message.set_rcode(simple.get("Status", 0))
for i, sn in enumerate(dns.message.MessageSection):
rr_list = simple.get(sn.name.title(), [])
for rr in rr_list:
- rdtype = dns.rdatatype.RdataType(rr['type'])
- rrs = message.find_rrset(i, dns.name.from_text(rr['name']),
- dns.rdataclass.IN, rdtype,
- create=True)
- if 'data' in rr:
- rrs.add(dns.rdata.from_text(dns.rdataclass.IN, rdtype,
- rr['data']), rr.get('TTL', 0))
+ rdtype = dns.rdatatype.RdataType(rr["type"])
+ rrs = message.find_rrset(
+ i,
+ dns.name.from_text(rr["name"]),
+ dns.rdataclass.IN,
+ rdtype,
+ create=True,
+ )
+ if "data" in rr:
+ rrs.add(
+ dns.rdata.from_text(dns.rdataclass.IN, rdtype, rr["data"]),
+ rr.get("TTL", 0),
+ )
# we don't decode the ecs_client_subnet field
return message
-a = dns.resolver.resolve('www.dnspython.org', 'a')
+a = dns.resolver.resolve("www.dnspython.org", "a")
p = to_doh_simple(a.response)
print(json.dumps(p, indent=4))
-response = requests.get('https://dns.google/resolve?', verify=True,
- params={'name': 'www.dnspython.org',
- 'type': 1})
+response = requests.get(
+ "https://dns.google/resolve?",
+ verify=True,
+ params={"name": "www.dnspython.org", "type": 1},
+)
p = json.loads(response.text)
m = from_doh_simple(p, True)
print(m)
def main():
- where = '1.1.1.1'
- qname = 'example.com.'
+ where = "1.1.1.1"
+ qname = "example.com."
# one method is to use context manager, session will automatically close
with requests.sessions.Session() as session:
q = dns.message.make_query(qname, dns.rdatatype.A)
# ... do more lookups
- where = 'https://dns.google/dns-query'
- qname = 'example.net.'
+ where = "https://dns.google/dns-query"
+ qname = "example.net."
# second method, close session manually
session = requests.sessions.Session()
q = dns.message.make_query(qname, dns.rdatatype.A)
# close the session when you're done
session.close()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()
#!/usr/bin/env python3
import dns.e164
+
n = dns.e164.from_e164("+1 555 1212")
print(n)
print(dns.e164.to_e164(n))
-
import dns.edns
import dns.message
import dns.query
# This example demonstrates how to use the EDNS client subnet option
-ADDRESS = '0.0.0.0' # replace this with the address you want to check
+ADDRESS = "0.0.0.0" # replace this with the address you want to check
PREFIX = 0 # replace this with a prefix length (typically 24 for IPv4)
ecs = dns.edns.ECSOption(ADDRESS, PREFIX)
-q = dns.message.make_query('www.google.com', 'A', use_edns=0, options=[ecs])
-r = dns.query.udp(q, '8.8.8.8')
+q = dns.message.make_query("www.google.com", "A", use_edns=0, options=[ecs])
+r = dns.query.udp(q, "8.8.8.8")
print(r)
-
import dns.query
import dns.resolver
-n = '.'
+n = "."
t = dns.rdatatype.SOA
-l = '199.7.83.42' # Address of l.root-servers.net
-i = '149.20.1.73' # Address of ns1.isc.org, for COOKIEs
+l = "199.7.83.42" # Address of l.root-servers.net
+i = "149.20.1.73" # Address of ns1.isc.org, for COOKIEs
q_list = []
q_list.append((l, dns.message.make_query(n, t)))
# The same query, but with EDNS0 turned on with no options
-q_list.append((l,dns.message.make_query(n, t, use_edns=0)))
+q_list.append((l, dns.message.make_query(n, t, use_edns=0)))
# Use use_edns() to specify EDNS0 options, such as buffer size
this_q = dns.message.make_query(n, t)
# With an NSID option
# use_edns=0 is not needed if options are specified)
-q_list.append((l, dns.message.make_query(n, t,\
- options=[dns.edns.GenericOption(dns.edns.OptionType.NSID, b'')])))
+q_list.append(
+ (
+ l,
+ dns.message.make_query(
+ n, t, options=[dns.edns.GenericOption(dns.edns.OptionType.NSID, b"")]
+ ),
+ )
+)
# With an NSID option, but with use_edns() to specify the options
this_q = dns.message.make_query(n, t)
-this_q.use_edns(0, options=[dns.edns.GenericOption(dns.edns.OptionType.NSID, b'')])
+this_q.use_edns(0, options=[dns.edns.GenericOption(dns.edns.OptionType.NSID, b"")])
q_list.append((l, this_q))
# With a COOKIE
-q_list.append((i, dns.message.make_query(n, t,\
- options=[dns.edns.GenericOption(dns.edns.OptionType.COOKIE, b'0xfe11ac99bebe3322')])))
+q_list.append(
+ (
+ i,
+ dns.message.make_query(
+ n,
+ t,
+ options=[
+ dns.edns.GenericOption(
+ dns.edns.OptionType.COOKIE, b"0xfe11ac99bebe3322"
+ )
+ ],
+ ),
+ )
+)
# With an ECS option using dns.edns.ECSOption to form the option
-q_list.append((l, dns.message.make_query(n, t,\
- options=[dns.edns.ECSOption('192.168.0.0', 20)])))
+q_list.append(
+ (l, dns.message.make_query(n, t, options=[dns.edns.ECSOption("192.168.0.0", 20)]))
+)
for (addr, q) in q_list:
- r = dns.query.udp(q, addr)
- if not r.options:
- print('No EDNS options returned')
- else:
- for o in r.options:
- print(o.otype.value, o.data)
- print()
-
+ r = dns.query.udp(q, addr)
+ if not r.options:
+ print("No EDNS options returned")
+ else:
+ for o in r.options:
+ print(o.otype.value, o.data)
+ print()
import dns.query
import dns.resolver
-n = '.'
+n = "."
t = dns.rdatatype.SOA
-l = 'google.com' # Address of l.root-servers.net, '199.7.83.42'
-i = 'ns1.isc.org' # Address of ns1.isc.org, for COOKIEs, '149.20.1.73'
+l = "google.com" # Address of l.root-servers.net, '199.7.83.42'
+i = "ns1.isc.org" # Address of ns1.isc.org, for COOKIEs, '149.20.1.73'
o_list = []
o_list.append((l, dict(payload=2000)))
# With an NSID option, but with use_edns() to specify the options
-edns_kwargs = dict(edns=0, options=[
- dns.edns.GenericOption(dns.edns.OptionType.NSID, b'')])
+edns_kwargs = dict(
+ edns=0, options=[dns.edns.GenericOption(dns.edns.OptionType.NSID, b"")]
+)
o_list.append((l, edns_kwargs))
# With a COOKIE
-o_list.append((i, dict(options=[
- dns.edns.GenericOption(dns.edns.OptionType.COOKIE, b'0xfe11ac99bebe3322')])))
+o_list.append(
+ (
+ i,
+ dict(
+ options=[
+ dns.edns.GenericOption(
+ dns.edns.OptionType.COOKIE, b"0xfe11ac99bebe3322"
+ )
+ ]
+ ),
+ )
+)
# With an ECS option using cloudflare dns address
-o_list.append((l, dict(options=[dns.edns.ECSOption('1.1.1.1', 24)])))
+o_list.append((l, dict(options=[dns.edns.ECSOption("1.1.1.1", 24)])))
# With an ECS option using the current machine address
import urllib.request
-external_ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
+external_ip = urllib.request.urlopen("https://ident.me").read().decode("utf8")
o_list.append((l, dict(options=[dns.edns.ECSOption(external_ip, 24)])))
for (addr, edns_kwargs) in o_list:
if edns_kwargs:
aresolver.use_edns(**edns_kwargs)
- aresolver.nameservers = ['8.8.8.8']
- print(list(aresolver.resolve(addr, 'A')))
+ aresolver.nameservers = ["8.8.8.8"]
+ print(list(aresolver.resolve(addr, "A")))
import dns.resolver
-answers = dns.resolver.resolve('nominum.com', 'MX')
+answers = dns.resolver.resolve("nominum.com", "MX")
for rdata in answers:
- print('Host', rdata.exchange, 'has preference', rdata.preference)
+ print("Host", rdata.exchange, "has preference", rdata.preference)
import dns.name
-n = dns.name.from_text('www.dnspython.org')
-o = dns.name.from_text('dnspython.org')
-print(n.is_subdomain(o)) # True
-print(n.is_superdomain(o)) # False
-print(n > o) # True
-rel = n.relativize(o) # rel is the relative name www
+n = dns.name.from_text("www.dnspython.org")
+o = dns.name.from_text("dnspython.org")
+print(n.is_subdomain(o)) # True
+print(n.is_superdomain(o)) # False
+print(n > o) # True
+rel = n.relativize(o) # rel is the relative name www
n2 = rel + o
-print(n2 == n) # True
-print(n.labels) # ['www', 'dnspython', 'org', '']
+print(n2 == n) # True
+print(n.labels) # ['www', 'dnspython', 'org', '']
# This way is just like nslookup/dig:
-qname = dns.name.from_text('amazon.com')
+qname = dns.name.from_text("amazon.com")
q = dns.message.make_query(qname, dns.rdatatype.NS)
-print('The query is:')
+print("The query is:")
print(q)
-print('')
-r = dns.query.udp(q, '8.8.8.8')
-print('The response is:')
+print("")
+r = dns.query.udp(q, "8.8.8.8")
+print("The response is:")
print(r)
-print('')
-print('The nameservers are:')
+print("")
+print("The nameservers are:")
ns_rrset = r.find_rrset(r.answer, qname, dns.rdataclass.IN, dns.rdatatype.NS)
for rr in ns_rrset:
print(rr.target)
-print('')
-print('')
+print("")
+print("")
# A higher-level way
import dns.resolver
resolver = dns.resolver.Resolver(configure=False)
-resolver.nameservers = ['8.8.8.8']
-answer = resolver.resolve('amazon.com', 'NS')
-print('The nameservers are:')
+resolver.nameservers = ["8.8.8.8"]
+answer = resolver.resolve("amazon.com", "NS")
+print("The nameservers are:")
for rr in answer:
print(rr.target)
# This sends a query with RD=0 for the root SOA RRset to the IP address
# for l.root-servers.net.
-q = dns.message.make_query('.', dns.rdatatype.SOA, flags=0)
-r = dns.query.udp(q, '199.7.83.42')
-print('\nThe flags in the response are {}'.format(dns.flags.to_text(r.flags)))
+q = dns.message.make_query(".", dns.rdatatype.SOA, flags=0)
+r = dns.query.udp(q, "199.7.83.42")
+print("\nThe flags in the response are {}".format(dns.flags.to_text(r.flags)))
print('The SOA in the response is "{}"'.format((r.answer)[0][0]))
from typing import cast
-address = '127.0.0.1'
+address = "127.0.0.1"
port = 53535
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
notify = dns.message.from_wire(wire)
try:
- soa = notify.find_rrset(notify.answer, notify.question[0].name,
- dns.rdataclass.IN, dns.rdatatype.SOA)
+ soa = notify.find_rrset(
+ notify.answer, notify.question[0].name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
# Do something with the SOA RR here
- print('The serial number for', soa.name, 'is', soa[0].serial)
+ print("The serial number for", soa.name, "is", soa[0].serial)
except KeyError:
# No SOA RR in the answer section.
pass
- response = dns.message.make_response(notify) # type: dns.message.Message
+ response = dns.message.make_response(notify) # type: dns.message.Message
response.flags |= dns.flags.AA
wire = response.to_wire(cast(dns.name.Name, response))
s.sendto(wire, address)
import dns.ipv4
import os.path
import sys
-from typing import Dict, List # pylint: disable=unused-import
+from typing import Dict, List # pylint: disable=unused-import
-reverse_map = {} # type: Dict[str, List[str]]
+reverse_map = {} # type: Dict[str, List[str]]
for filename in sys.argv[1:]:
- zone = dns.zone.from_file(filename, os.path.basename(filename),
- relativize=False)
- for (name, ttl, rdata) in zone.iterate_rdatas('A'):
+ zone = dns.zone.from_file(filename, os.path.basename(filename), relativize=False)
+ for (name, ttl, rdata) in zone.iterate_rdatas("A"):
print(type(rdata))
try:
reverse_map[rdata.address].append(name.to_text())
#!/usr/bin/env python3
import dns.reversename
+
n = dns.reversename.from_address("127.0.0.1")
print(n)
print(dns.reversename.to_address(n))
import dns.resolver
import dns.zone
-soa_answer = dns.resolver.resolve('dnspython.org', 'SOA')
-master_answer = dns.resolver.resolve(soa_answer[0].mname, 'A')
+soa_answer = dns.resolver.resolve("dnspython.org", "SOA")
+master_answer = dns.resolver.resolve(soa_answer[0].mname, "A")
-z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, 'dnspython.org'))
+z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, "dnspython.org"))
for n in sorted(z.nodes.keys()):
print(z[n].to_text(n))
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""See diff_zones.__doc__ for more information"""
-from typing import cast, Union, Any # pylint: disable=unused-import
+from typing import cast, Union, Any # pylint: disable=unused-import
-__all__ = ['diff_zones', 'format_changes_plain', 'format_changes_html']
+__all__ = ["diff_zones", "format_changes_plain", "format_changes_html"]
try:
import dns.zone
raise SystemExit("Please install dnspython")
-def diff_zones(zone1, # type: dns.zone.Zone
- zone2, # type: dns.zone.Zone
- ignore_ttl=False,
- ignore_soa=False
- ): # type: (...) -> list
+def diff_zones(
+ zone1, # type: dns.zone.Zone
+ zone2, # type: dns.zone.Zone
+ ignore_ttl=False,
+ ignore_soa=False,
+): # type: (...) -> list
"""diff_zones(zone1, zone2, ignore_ttl=False, ignore_soa=False) -> changes
Compares two dns.zone.Zone objects and returns a list of all changes
in the format (name, oldnode, newnode).
changes.append((str(name), n3, n4))
return changes
-def _nodes_differ(n1, # type: dns.node.Node
- n2, # type: dns.node.Node
- ignore_ttl, # type: bool
- ignore_soa # type: bool
- ): # type: (...) -> bool
+
+def _nodes_differ(
+ n1, # type: dns.node.Node
+ n2, # type: dns.node.Node
+ ignore_ttl, # type: bool
+ ignore_soa, # type: bool
+): # type: (...) -> bool
if ignore_soa or not ignore_ttl:
# Compare datasets directly
for r in n1.rdatasets:
else:
return n1 != n2
-def format_changes_plain(oldf, # type: str
- newf, # type: str
- changes, # type: list
- ignore_ttl=False
- ): # type: (...) -> str
+
+def format_changes_plain(
+ oldf, # type: str
+ newf, # type: str
+ changes, # type: list
+ ignore_ttl=False,
+): # type: (...) -> str
"""format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str
Given 2 filenames and a list of changes from diff_zones, produce diff-like
output. If ignore_ttl is True, TTL-only changes are not displayed"""
ret += "@ %s\n" % name
if not old:
for r in new.rdatasets:
- ret += "+ %s\n" % str(r).replace('\n', '\n+ ')
+ ret += "+ %s\n" % str(r).replace("\n", "\n+ ")
elif not new:
for r in old.rdatasets:
- ret += "- %s\n" % str(r).replace('\n', '\n+ ')
+ ret += "- %s\n" % str(r).replace("\n", "\n+ ")
else:
for r in old.rdatasets:
if r not in new.rdatasets or (
- r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl and
- not ignore_ttl
+ r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl
+ and not ignore_ttl
):
- ret += "- %s\n" % str(r).replace('\n', '\n+ ')
+ ret += "- %s\n" % str(r).replace("\n", "\n+ ")
for r in new.rdatasets:
if r not in old.rdatasets or (
- r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl and
- not ignore_ttl
+ r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl
+ and not ignore_ttl
):
- ret += "+ %s\n" % str(r).replace('\n', '\n+ ')
+ ret += "+ %s\n" % str(r).replace("\n", "\n+ ")
return ret
-def format_changes_html(oldf, # type: str
- newf, # type: str
- changes, # type: list
- ignore_ttl=False
- ): # type: (...) -> str
+
+def format_changes_html(
+ oldf, # type: str
+ newf, # type: str
+ changes, # type: list
+ ignore_ttl=False,
+): # type: (...) -> str
"""format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str
Given 2 filenames and a list of changes from diff_zones, produce nice html
output. If ignore_ttl is True, TTL-only changes are not displayed"""
- ret = '''<table class="zonediff">
+ ret = """<table class="zonediff">
<thead>
<tr>
<th> </th>
<th class="new">%s</th>
</tr>
</thead>
- <tbody>\n''' % (oldf, newf)
+ <tbody>\n""" % (
+ oldf,
+ newf,
+ )
for name, old, new in changes:
ret += ' <tr class="rdata">\n <td class="rdname">%s</td>\n' % name
ret += (
' <td class="old"> </td>\n'
' <td class="new">%s</td>\n'
- ) % str(r).replace('\n', '<br />')
+ ) % str(r).replace("\n", "<br />")
elif not new:
for r in old.rdatasets:
ret += (
' <td class="old">%s</td>\n'
' <td class="new"> </td>\n'
- ) % str(r).replace('\n', '<br />')
+ ) % str(r).replace("\n", "<br />")
else:
ret += ' <td class="old">'
for r in old.rdatasets:
if r not in new.rdatasets or (
- r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl and
- not ignore_ttl
+ r.ttl != new.find_rdataset(r.rdclass, r.rdtype).ttl
+ and not ignore_ttl
):
- ret += str(r).replace('\n', '<br />')
- ret += '</td>\n'
+ ret += str(r).replace("\n", "<br />")
+ ret += "</td>\n"
ret += ' <td class="new">'
for r in new.rdatasets:
if r not in old.rdatasets or (
- r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl and
- not ignore_ttl
+ r.ttl != old.find_rdataset(r.rdclass, r.rdtype).ttl
+ and not ignore_ttl
):
- ret += str(r).replace('\n', '<br />')
- ret += '</td>\n'
- ret += ' </tr>\n'
- return ret + ' </tbody>\n</table>'
+ ret += str(r).replace("\n", "<br />")
+ ret += "</td>\n"
+ ret += " </tr>\n"
+ return ret + " </tbody>\n</table>"
# Make this module usable as a script too.
-def main(): # type: () -> None
+def main(): # type: () -> None
import argparse
import subprocess
import sys
The differences shown will be logical differences, not textual differences.
"""
p = argparse.ArgumentParser(usage=usage)
- p.add_argument('-s', '--ignore-soa', action="store_true", default=False, dest="ignore_soa",
- help="Ignore SOA-only changes to records")
- p.add_argument('-t', '--ignore-ttl', action="store_true", default=False, dest="ignore_ttl",
- help="Ignore TTL-only changes to Rdata")
- p.add_argument('-T', '--traceback', action="store_true", default=False, dest="tracebacks",
- help="Show python tracebacks when errors occur")
- p.add_argument('-H', '--html', action="store_true", default=False, dest="html",
- help="Print HTML output")
- p.add_argument('-g', '--git', action="store_true", default=False, dest="use_git",
- help="Use git revisions instead of real files")
- p.add_argument('-b', '--bzr', action="store_true", default=False, dest="use_bzr",
- help="Use bzr revisions instead of real files")
- p.add_argument('-r', '--rcs', action="store_true", default=False, dest="use_rcs",
- help="Use rcs revisions instead of real files")
+ p.add_argument(
+ "-s",
+ "--ignore-soa",
+ action="store_true",
+ default=False,
+ dest="ignore_soa",
+ help="Ignore SOA-only changes to records",
+ )
+ p.add_argument(
+ "-t",
+ "--ignore-ttl",
+ action="store_true",
+ default=False,
+ dest="ignore_ttl",
+ help="Ignore TTL-only changes to Rdata",
+ )
+ p.add_argument(
+ "-T",
+ "--traceback",
+ action="store_true",
+ default=False,
+ dest="tracebacks",
+ help="Show python tracebacks when errors occur",
+ )
+ p.add_argument(
+ "-H",
+ "--html",
+ action="store_true",
+ default=False,
+ dest="html",
+ help="Print HTML output",
+ )
+ p.add_argument(
+ "-g",
+ "--git",
+ action="store_true",
+ default=False,
+ dest="use_git",
+ help="Use git revisions instead of real files",
+ )
+ p.add_argument(
+ "-b",
+ "--bzr",
+ action="store_true",
+ default=False,
+ dest="use_bzr",
+ help="Use bzr revisions instead of real files",
+ )
+ p.add_argument(
+ "-r",
+ "--rcs",
+ action="store_true",
+ default=False,
+ dest="use_rcs",
+ help="Use rcs revisions instead of real files",
+ )
opts, args = p.parse_args()
opts.use_vc = opts.use_git or opts.use_bzr or opts.use_rcs
- def _open(what, err): # type: (Union[list,str], str) -> Any
+ def _open(what, err): # type: (Union[list,str], str) -> Any
if isinstance(what, list):
# Must be a list, open subprocess
try:
else:
# Open as normal file
try:
- return open(what, 'rb')
+ return open(what, "rb")
except IOError:
sys.stderr.write(err + "\n")
if opts.tracebacks:
old, new = None, None
oldz, newz = None, None
if opts.use_bzr:
- old = _open(["bzr", "cat", "-r" + oldr, filename],
- "Unable to retrieve revision {} of {}".format(oldr, filename))
+ old = _open(
+ ["bzr", "cat", "-r" + oldr, filename],
+ "Unable to retrieve revision {} of {}".format(oldr, filename),
+ )
if newr is not None:
- new = _open(["bzr", "cat", "-r" + newr, filename],
- "Unable to retrieve revision {} of {}".format(newr, filename))
+ new = _open(
+ ["bzr", "cat", "-r" + newr, filename],
+ "Unable to retrieve revision {} of {}".format(newr, filename),
+ )
elif opts.use_git:
- old = _open(["git", "show", oldn],
- "Unable to retrieve revision {} of {}".format(oldr, filename))
+ old = _open(
+ ["git", "show", oldn],
+ "Unable to retrieve revision {} of {}".format(oldr, filename),
+ )
if newr is not None:
- new = _open(["git", "show", newn],
- "Unable to retrieve revision {} of {}".format(newr, filename))
+ new = _open(
+ ["git", "show", newn],
+ "Unable to retrieve revision {} of {}".format(newr, filename),
+ )
elif opts.use_rcs:
- old = _open(["co", "-q", "-p", "-r" + oldr, filename],
- "Unable to retrieve revision {} of {}".format(oldr, filename))
+ old = _open(
+ ["co", "-q", "-p", "-r" + oldr, filename],
+ "Unable to retrieve revision {} of {}".format(oldr, filename),
+ )
if newr is not None:
- new = _open(["co", "-q", "-p", "-r" + newr, filename],
- "Unable to retrieve revision {} of {}".format(newr, filename))
+ new = _open(
+ ["co", "-q", "-p", "-r" + newr, filename],
+ "Unable to retrieve revision {} of {}".format(newr, filename),
+ )
if not opts.use_vc:
old = _open(oldn, "Unable to open %s" % oldn)
if not opts.use_vc or newr is None:
# Parse the zones
try:
- oldz = dns.zone.from_file(old, origin='.', check_origin=False)
+ oldz = dns.zone.from_file(old, origin=".", check_origin=False)
except dns.exception.DNSException:
sys.stderr.write("Incorrect zonefile: %s\n" % old)
if opts.tracebacks:
traceback.print_exc()
try:
- newz = dns.zone.from_file(new, origin='.', check_origin=False)
+ newz = dns.zone.from_file(new, origin=".", check_origin=False)
except dns.exception.DNSException:
sys.stderr.write("Incorrect zonefile: %s\n" % new)
if opts.tracebacks:
print(format_changes_plain(oldn, newn, changes, opts.ignore_ttl))
sys.exit(1)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()
raise-missing-from, # we should start doing this, but too noisy for now
consider-using-f-string,
unspecified-encoding,
+ useless-super-delegation, # not against this, but we have to do it for mypy happiness
[REPORTS]
msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg})'
[FORMAT]
-max-line-length=120
+max-line-length=88
try:
- sys.argv.remove("--cython-compile")
+ sys.argv.remove("--cython-compile")
except ValueError:
- compile_cython = False
+ compile_cython = False
else:
compile_cython = True
from Cython.Build import cythonize
- ext_modules = cythonize(['dns/*.py', 'dns/rdtypes/*.py', 'dns/rdtypes/*/*.py'],
- language_level='3')
+
+ ext_modules = cythonize(
+ ["dns/*.py", "dns/rdtypes/*.py", "dns/rdtypes/*/*.py"], language_level="3"
+ )
kwargs = {
- 'ext_modules': ext_modules if compile_cython else None,
- 'zip_safe': False if compile_cython else None,
- }
+ "ext_modules": ext_modules if compile_cython else None,
+ "zip_safe": False if compile_cython else None,
+}
setup(**kwargs)
import dns.rdtypes.nsbase
+
class MD(dns.rdtypes.nsbase.NSBase):
"""Test MD record."""
import dns.message
import dns.rcode
+
async def read_exactly(stream, count):
"""Read the specified number of bytes from stream. Keep trying until we
either get the desired amount, or we hit EOF.
"""
- s = b''
+ s = b""
while count > 0:
n = await stream.receive_some(count)
- if n == b'':
+ if n == b"":
raise EOFError
count = count - len(n)
s = s + n
return s
+
class ConnectionType(enum.IntEnum):
UDP = 1
TCP = 2
+
class Request:
def __init__(self, message, wire, peer, local, connection_type):
self.message = message
def qtype(self):
return self.question.rdtype
+
class Server(threading.Thread):
"""The nanoserver is a nameserver skeleton suitable for faking a DNS
called.
"""
- def __init__(self, address='127.0.0.1', port=0, enable_udp=True,
- enable_tcp=True, use_thread=True, origin=None,
- keyring=None):
+ def __init__(
+ self,
+ address="127.0.0.1",
+ port=0,
+ enable_udp=True,
+ enable_tcp=True,
+ use_thread=True,
+ origin=None,
+ keyring=None,
+ ):
super().__init__()
self.address = address
self.port = port
try:
while True:
if self.enable_udp:
- self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
- 0)
+ self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
self.udp.bind((self.address, self.port))
self.udp_address = self.udp.getsockname()
if self.enable_tcp:
- self.tcp = socket.socket(socket.AF_INET,
- socket.SOCK_STREAM, 0)
- self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
- 1)
+ self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+ self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if self.port == 0 and self.enable_udp:
try:
self.tcp.bind((self.address, self.udp_address[1]))
except OSError as e:
- if e.errno == errno.EADDRINUSE and \
- len(open_udp_sockets) < 100:
+ if (
+ e.errno == errno.EADDRINUSE
+ and len(open_udp_sockets) < 100
+ ):
open_udp_sockets.append(self.udp)
continue
raise
while True:
try:
(wire, peer) = await sock.recvfrom(65535)
- for wire in self.handle_wire(wire, peer, local,
- ConnectionType.UDP):
+ for wire in self.handle_wire(wire, peer, local, ConnectionType.UDP):
await sock.sendto(wire, peer)
except Exception:
pass
ldata = await read_exactly(stream, 2)
(l,) = struct.unpack("!H", ldata)
wire = await read_exactly(stream, l)
- for wire in self.handle_wire(wire, peer, local,
- ConnectionType.TCP):
+ for wire in self.handle_wire(wire, peer, local, ConnectionType.TCP):
l = len(wire)
stream_message = struct.pack("!H", l) + wire
await stream.send_all(stream_message)
self.tcp = None # we own cleanup
listener = trio.SocketListener(sock)
async with trio.open_nursery() as nursery:
- serve = functools.partial(trio.serve_listeners, self.serve_tcp,
- [listener], handler_nursery=nursery)
+ serve = functools.partial(
+ trio.serve_listeners,
+ self.serve_tcp,
+ [listener],
+ handler_nursery=nursery,
+ )
nursery.start_soon(serve)
async def main(self):
def run(self):
if not self.use_thread:
- raise RuntimeError('start() called on a use_thread=False Server')
+ raise RuntimeError("start() called on a use_thread=False Server")
trio.run(self.main)
+
if __name__ == "__main__":
import sys
import time
async def trio_main():
try:
with Server(port=5354, use_thread=False) as server:
- print(f'Trio mode: listening on UDP: {server.udp_address}, ' +
- f'TCP: {server.tcp_address}')
+ print(
+ f"Trio mode: listening on UDP: {server.udp_address}, "
+ + f"TCP: {server.tcp_address}"
+ )
async with trio.open_nursery() as nursery:
nursery.start_soon(server.main)
except Exception:
def threaded_main():
with Server(port=5354) as server:
- print(f'Thread Mode: listening on UDP: {server.udp_address}, ' +
- f'TCP: {server.tcp_address}')
+ print(
+ f"Thread Mode: listening on UDP: {server.udp_address}, "
+ + f"TCP: {server.tcp_address}"
+ )
time.sleep(300)
- if len(sys.argv) > 1 and sys.argv[1] == 'trio':
+ if len(sys.argv) > 1 and sys.argv[1] == "trio":
trio.run(trio_main)
else:
threaded_main()
import dns.rdtypes.txtbase
+
class STXT(dns.rdtypes.txtbase.TXTBase):
"""Test singleton TXT-like record"""
import dns.ipv4
import dns.ipv6
+
class IPv4Tests(unittest.TestCase):
def test_valid(self):
valid = (
"192.0.2.128",
)
for s in valid:
- self.assertEqual(dns.ipv4.inet_aton(s),
- socket.inet_pton(socket.AF_INET, s))
+ self.assertEqual(dns.ipv4.inet_aton(s), socket.inet_pton(socket.AF_INET, s))
def test_invalid(self):
invalid = (
"::",
)
for s in invalid:
- with self.assertRaises(dns.exception.SyntaxError,
- msg=f'invalid IPv4 address: "{s}"'):
+ with self.assertRaises(
+ dns.exception.SyntaxError, msg=f'invalid IPv4 address: "{s}"'
+ ):
dns.ipv4.inet_aton(s)
+
class IPv6Tests(unittest.TestCase):
def test_valid(self):
valid = (
}
for s in valid:
- if sys.platform == 'win32' and s in win32_invalid:
+ if sys.platform == "win32" and s in win32_invalid:
# socket.inet_pton() on win32 rejects some valid (as
# far as we can tell) IPv6 addresses. Skip them.
continue
- self.assertEqual(dns.ipv6.inet_aton(s),
- socket.inet_pton(socket.AF_INET6, s))
+ self.assertEqual(
+ dns.ipv6.inet_aton(s), socket.inet_pton(socket.AF_INET6, s)
+ )
def test_invalid(self):
invalid = (
"':10.0.0.1",
)
for s in invalid:
- with self.assertRaises(dns.exception.SyntaxError,
- msg=f'invalid IPv6 address: "{s}"'):
+ with self.assertRaises(
+ dns.exception.SyntaxError, msg=f'invalid IPv6 address: "{s}"'
+ ):
dns.ipv6.inet_aton(s)
# skip those if it's not there.
_network_available = True
try:
- socket.gethostbyname('dnspython.org')
+ socket.gethostbyname("dnspython.org")
except socket.gaierror:
_network_available = False
_systemd_resolved_present = False
try:
_resolver = dns.resolver.Resolver()
- if _resolver.nameservers == ['127.0.0.53']:
+ if _resolver.nameservers == ["127.0.0.53"]:
_systemd_resolved_present = True
except Exception:
pass
# Probe for IPv4 and IPv6
query_addresses = []
-for (af, address) in ((socket.AF_INET, '8.8.8.8'),
- (socket.AF_INET6, '2001:4860:4860::8888')):
+for (af, address) in (
+ (socket.AF_INET, "8.8.8.8"),
+ (socket.AF_INET6, "2001:4860:4860::8888"),
+):
try:
with socket.socket(af, socket.SOCK_DGRAM) as s:
# Connecting a UDP socket is supposed to return ENETUNREACH if
except Exception:
pass
-KNOWN_ANYCAST_DOH_RESOLVER_URLS = ['https://cloudflare-dns.com/dns-query',
- 'https://dns.google/dns-query',
- # 'https://dns11.quad9.net/dns-query',
- ]
+KNOWN_ANYCAST_DOH_RESOLVER_URLS = [
+ "https://cloudflare-dns.com/dns-query",
+ "https://dns.google/dns-query",
+ # 'https://dns11.quad9.net/dns-query',
+]
class AsyncDetectionTests(unittest.TestCase):
- sniff_result = 'asyncio'
+ sniff_result = "asyncio"
def async_run(self, afunc):
return asyncio.run(afunc())
def test_sniff(self):
dns.asyncbackend._default_backend = None
+
async def run():
self.assertEqual(dns.asyncbackend.sniff(), self.sniff_result)
+
self.async_run(run)
def test_get_default_backend(self):
dns.asyncbackend._default_backend = None
+
async def run():
backend = dns.asyncbackend.get_default_backend()
self.assertEqual(backend.name(), self.sniff_result)
+
self.async_run(run)
+
class NoSniffioAsyncDetectionTests(AsyncDetectionTests):
expect_raise = False
def test_sniff(self):
dns.asyncbackend._default_backend = None
if self.expect_raise:
+
async def abad():
dns.asyncbackend.sniff()
+
def bad():
self.async_run(abad)
+
self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad)
else:
super().test_sniff()
def test_get_default_backend(self):
dns.asyncbackend._default_backend = None
if self.expect_raise:
+
async def abad():
dns.asyncbackend.get_default_backend()
+
def bad():
self.async_run(abad)
+
self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad)
else:
super().test_get_default_backend()
class MiscBackend(unittest.TestCase):
def test_sniff_without_run_loop(self):
dns.asyncbackend._default_backend = None
+
def bad():
dns.asyncbackend.sniff()
+
self.assertRaises(dns.asyncbackend.AsyncLibraryNotFoundError, bad)
def test_bogus_backend(self):
def bad():
- dns.asyncbackend.get_backend('bogus')
+ dns.asyncbackend.get_backend("bogus")
+
self.assertRaises(NotImplementedError, bad)
self.assertEqual(t, None)
t = dns.asyncquery._source_tuple(socket.AF_INET6, None, 0)
self.assertEqual(t, None)
- t = dns.asyncquery._source_tuple(socket.AF_INET, '1.2.3.4', 53)
- self.assertEqual(t, ('1.2.3.4', 53))
- t = dns.asyncquery._source_tuple(socket.AF_INET6, '1::2', 53)
- self.assertEqual(t, ('1::2', 53))
+ t = dns.asyncquery._source_tuple(socket.AF_INET, "1.2.3.4", 53)
+ self.assertEqual(t, ("1.2.3.4", 53))
+ t = dns.asyncquery._source_tuple(socket.AF_INET6, "1::2", 53)
+ self.assertEqual(t, ("1::2", 53))
t = dns.asyncquery._source_tuple(socket.AF_INET, None, 53)
- self.assertEqual(t, ('0.0.0.0', 53))
+ self.assertEqual(t, ("0.0.0.0", 53))
t = dns.asyncquery._source_tuple(socket.AF_INET6, None, 53)
- self.assertEqual(t, ('::', 53))
+ self.assertEqual(t, ("::", 53))
@unittest.skipIf(not _network_available, "Internet not reachable")
class AsyncTests(unittest.TestCase):
- connect_udp = sys.platform == 'win32'
+ connect_udp = sys.platform == "win32"
def setUp(self):
- self.backend = dns.asyncbackend.set_default_backend('asyncio')
+ self.backend = dns.asyncbackend.set_default_backend("asyncio")
def async_run(self, afunc):
return asyncio.run(afunc())
def testResolve(self):
async def run():
- answer = await dns.asyncresolver.resolve('dns.google.', 'A')
+ answer = await dns.asyncresolver.resolve("dns.google.", "A")
return set([rdata.address for rdata in answer])
+
seen = self.async_run(run)
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testResolveAddress(self):
async def run():
- return await dns.asyncresolver.resolve_address('8.8.8.8')
+ return await dns.asyncresolver.resolve_address("8.8.8.8")
+
answer = self.async_run(run)
- dnsgoogle = dns.name.from_text('dns.google.')
+ dnsgoogle = dns.name.from_text("dns.google.")
self.assertEqual(answer[0].target, dnsgoogle)
def testCanonicalNameNoCNAME(self):
- cname = dns.name.from_text('www.google.com')
+ cname = dns.name.from_text("www.google.com")
+
async def run():
- return await dns.asyncresolver.canonical_name('www.google.com')
+ return await dns.asyncresolver.canonical_name("www.google.com")
+
self.assertEqual(self.async_run(run), cname)
def testCanonicalNameCNAME(self):
- name = dns.name.from_text('www.dnspython.org')
- cname = dns.name.from_text('dmfrjf4ips8xa.cloudfront.net')
+ name = dns.name.from_text("www.dnspython.org")
+ cname = dns.name.from_text("dmfrjf4ips8xa.cloudfront.net")
+
async def run():
return await dns.asyncresolver.canonical_name(name)
+
self.assertEqual(self.async_run(run), cname)
@unittest.skipIf(_systemd_resolved_present, "systemd-resolved in use")
def testCanonicalNameDangling(self):
- name = dns.name.from_text('dangling-cname.dnspython.org')
- cname = dns.name.from_text('dangling-target.dnspython.org')
+ name = dns.name.from_text("dangling-cname.dnspython.org")
+ cname = dns.name.from_text("dangling-target.dnspython.org")
+
async def run():
return await dns.asyncresolver.canonical_name(name)
- self.assertEqual(self.async_run(run), cname)
+ self.assertEqual(self.async_run(run), cname)
def testZoneForName1(self):
async def run():
- name = dns.name.from_text('www.dnspython.org.')
+ name = dns.name.from_text("www.dnspython.org.")
return await dns.asyncresolver.zone_for_name(name)
- ezname = dns.name.from_text('dnspython.org.')
+
+ ezname = dns.name.from_text("dnspython.org.")
zname = self.async_run(run)
self.assertEqual(zname, ezname)
def testZoneForName2(self):
async def run():
- name = dns.name.from_text('a.b.www.dnspython.org.')
+ name = dns.name.from_text("a.b.www.dnspython.org.")
return await dns.asyncresolver.zone_for_name(name)
- ezname = dns.name.from_text('dnspython.org.')
+
+ ezname = dns.name.from_text("dnspython.org.")
zname = self.async_run(run)
self.assertEqual(zname, ezname)
def testZoneForName3(self):
async def run():
- name = dns.name.from_text('dnspython.org.')
+ name = dns.name.from_text("dnspython.org.")
return await dns.asyncresolver.zone_for_name(name)
- ezname = dns.name.from_text('dnspython.org.')
+
+ ezname = dns.name.from_text("dnspython.org.")
zname = self.async_run(run)
self.assertEqual(zname, ezname)
def testZoneForName4(self):
def bad():
- name = dns.name.from_text('dnspython.org', None)
+ name = dns.name.from_text("dnspython.org", None)
+
async def run():
return await dns.asyncresolver.zone_for_name(name)
+
self.async_run(run)
+
self.assertRaises(dns.resolver.NotAbsolute, bad)
def testQueryUDP(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
q = dns.message.make_query(qname, dns.rdatatype.A)
return await dns.asyncquery.udp(q, address, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryUDPWithSocket(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
if self.connect_udp:
- dtuple=(address, 53)
+ dtuple = (address, 53)
else:
- dtuple=None
+ dtuple = None
async with await self.backend.make_socket(
- dns.inet.af_for_address(address),
- socket.SOCK_DGRAM, 0, None, dtuple) as s:
+ dns.inet.af_for_address(address), socket.SOCK_DGRAM, 0, None, dtuple
+ ) as s:
q = dns.message.make_query(qname, dns.rdatatype.A)
- return await dns.asyncquery.udp(q, address, sock=s,
- timeout=2)
+ return await dns.asyncquery.udp(q, address, sock=s, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryTCP(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
q = dns.message.make_query(qname, dns.rdatatype.A)
return await dns.asyncquery.tcp(q, address, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryTCPWithSocket(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
async with await self.backend.make_socket(
- dns.inet.af_for_address(address),
- socket.SOCK_STREAM, 0,
- None,
- (address, 53), 2) as s:
+ dns.inet.af_for_address(address),
+ socket.SOCK_STREAM,
+ 0,
+ None,
+ (address, 53),
+ 2,
+ ) as s:
# for basic coverage
await s.getsockname()
q = dns.message.make_query(qname, dns.rdatatype.A)
- return await dns.asyncquery.tcp(q, address, sock=s,
- timeout=2)
+ return await dns.asyncquery.tcp(q, address, sock=s, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
@unittest.skipIf(not _ssl_available, "SSL not available")
def testQueryTLS(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
q = dns.message.make_query(qname, dns.rdatatype.A)
return await dns.asyncquery.tls(q, address, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
@unittest.skipIf(not _ssl_available, "SSL not available")
def testQueryTLSWithSocket(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
async with await self.backend.make_socket(
- dns.inet.af_for_address(address),
- socket.SOCK_STREAM, 0,
- None,
- (address, 853), 2,
- ssl_context, None) as s:
+ dns.inet.af_for_address(address),
+ socket.SOCK_STREAM,
+ 0,
+ None,
+ (address, 853),
+ 2,
+ ssl_context,
+ None,
+ ) as s:
# for basic coverage
await s.getsockname()
q = dns.message.make_query(qname, dns.rdatatype.A)
- return await dns.asyncquery.tls(q, '8.8.8.8', sock=s,
- timeout=2)
+ return await dns.asyncquery.tls(q, "8.8.8.8", sock=s, timeout=2)
+
response = self.async_run(run)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryUDPFallback(self):
for address in query_addresses:
- qname = dns.name.from_text('.')
+ qname = dns.name.from_text(".")
+
async def run():
q = dns.message.make_query(qname, dns.rdatatype.DNSKEY)
- return await dns.asyncquery.udp_with_fallback(q, address,
- timeout=2)
+ return await dns.asyncquery.udp_with_fallback(q, address, timeout=2)
+
(_, tcp) = self.async_run(run)
self.assertTrue(tcp)
def testQueryUDPFallbackNoFallback(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
+
async def run():
q = dns.message.make_query(qname, dns.rdatatype.A)
- return await dns.asyncquery.udp_with_fallback(q, address,
- timeout=2)
+ return await dns.asyncquery.udp_with_fallback(q, address, timeout=2)
+
(_, tcp) = self.async_run(run)
self.assertFalse(tcp)
def testUDPReceiveQuery(self):
if self.connect_udp:
- self.skipTest('test needs connectionless sockets')
+ self.skipTest("test needs connectionless sockets")
+
async def run():
async with await self.backend.make_socket(
- socket.AF_INET, socket.SOCK_DGRAM,
- source=('127.0.0.1', 0)) as listener:
+ socket.AF_INET, socket.SOCK_DGRAM, source=("127.0.0.1", 0)
+ ) as listener:
listener_address = await listener.getsockname()
async with await self.backend.make_socket(
- socket.AF_INET, socket.SOCK_DGRAM,
- source=('127.0.0.1', 0)) as sender:
+ socket.AF_INET, socket.SOCK_DGRAM, source=("127.0.0.1", 0)
+ ) as sender:
sender_address = await sender.getsockname()
- q = dns.message.make_query('dns.google', dns.rdatatype.A)
+ q = dns.message.make_query("dns.google", dns.rdatatype.A)
await dns.asyncquery.send_udp(sender, q, listener_address)
expiration = time.time() + 2
(_, _, recv_address) = await dns.asyncquery.receive_udp(
- listener, expiration=expiration)
+ listener, expiration=expiration
+ )
return (sender_address, recv_address)
+
(sender_address, recv_address) = self.async_run(run)
self.assertEqual(sender_address, recv_address)
def testUDPReceiveTimeout(self):
if self.connect_udp:
- self.skipTest('test needs connectionless sockets')
+ self.skipTest("test needs connectionless sockets")
+
async def arun():
- async with await self.backend.make_socket(socket.AF_INET,
- socket.SOCK_DGRAM, 0,
- ('127.0.0.1', 0)) as s:
+ async with await self.backend.make_socket(
+ socket.AF_INET, socket.SOCK_DGRAM, 0, ("127.0.0.1", 0)
+ ) as s:
try:
# for basic coverage
await s.getpeername()
# we expect failure as we haven't connected the socket
pass
await s.recvfrom(1000, 0.05)
+
def run():
self.async_run(arun)
+
self.assertRaises(dns.exception.Timeout, run)
@unittest.skipIf(not dns.query._have_httpx, "httpx not available")
def testDOHGetRequest(self):
- if self.backend.name() == 'curio':
- self.skipTest('anyio dropped curio support')
+ if self.backend.name() == "curio":
+ self.skipTest("anyio dropped curio support")
+
async def run():
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = await dns.asyncquery.https(q, nameserver_url, post=False,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = await dns.asyncquery.https(q, nameserver_url, post=False, timeout=4)
self.assertTrue(q.is_response(r))
+
self.async_run(run)
@unittest.skipIf(not dns.query._have_httpx, "httpx not available")
def testDOHGetRequestHttp1(self):
- if self.backend.name() == 'curio':
- self.skipTest('anyio dropped curio support')
+ if self.backend.name() == "curio":
+ self.skipTest("anyio dropped curio support")
+
async def run():
saved_have_http2 = dns.query._have_http2
try:
dns.query._have_http2 = False
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = await dns.asyncquery.https(q, nameserver_url, post=False,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = await dns.asyncquery.https(q, nameserver_url, post=False, timeout=4)
self.assertTrue(q.is_response(r))
finally:
dns.query._have_http2 = saved_have_http2
+
self.async_run(run)
@unittest.skipIf(not dns.query._have_httpx, "httpx not available")
def testDOHPostRequest(self):
- if self.backend.name() == 'curio':
- self.skipTest('anyio dropped curio support')
+ if self.backend.name() == "curio":
+ self.skipTest("anyio dropped curio support")
+
async def run():
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = await dns.asyncquery.https(q, nameserver_url, post=True,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = await dns.asyncquery.https(q, nameserver_url, post=True, timeout=4)
self.assertTrue(q.is_response(r))
+
self.async_run(run)
@unittest.skipIf(not dns.query._have_httpx, "httpx not available")
def testResolverDOH(self):
- if self.backend.name() == 'curio':
- self.skipTest('anyio dropped curio support')
+ if self.backend.name() == "curio":
+ self.skipTest("anyio dropped curio support")
+
async def run():
res = dns.asyncresolver.Resolver(configure=False)
- res.nameservers = ['https://dns.google/dns-query']
- answer = await res.resolve('dns.google', 'A', backend=self.backend)
+ res.nameservers = ["https://dns.google/dns-query"]
+ answer = await res.resolve("dns.google", "A", backend=self.backend)
seen = set([rdata.address for rdata in answer])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
+
self.async_run(run)
def testSleep(self):
await self.backend.sleep(0.1)
after = time.time()
self.assertTrue(after - before >= 0.1)
+
self.async_run(run)
+
try:
import trio
import sniffio
class TrioAsyncDetectionTests(AsyncDetectionTests):
- sniff_result = 'trio'
+ sniff_result = "trio"
+
def async_run(self, afunc):
return trio.run(afunc)
class TrioNoSniffioAsyncDetectionTests(NoSniffioAsyncDetectionTests):
expect_raise = True
+
def async_run(self, afunc):
return trio.run(afunc)
class TrioAsyncTests(AsyncTests):
connect_udp = False
+
def setUp(self):
- self.backend = dns.asyncbackend.set_default_backend('trio')
+ self.backend = dns.asyncbackend.set_default_backend("trio")
def async_run(self, afunc):
return trio.run(afunc)
+
except ImportError:
pass
import sniffio
class CurioAsyncDetectionTests(AsyncDetectionTests):
- sniff_result = 'curio'
+ sniff_result = "curio"
+
def async_run(self, afunc):
return curio.run(afunc)
class CurioNoSniffioAsyncDetectionTests(NoSniffioAsyncDetectionTests):
expect_raise = True
+
def async_run(self, afunc):
return curio.run(afunc)
class CurioAsyncTests(AsyncTests):
connect_udp = False
+
def setUp(self):
- self.backend = dns.asyncbackend.set_default_backend('curio')
+ self.backend = dns.asyncbackend.set_default_backend("curio")
def async_run(self, afunc):
return curio.run(afunc)
+
except ImportError:
pass
class BugsTestCase(unittest.TestCase):
-
def test_float_LOC(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC,
- u"30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m")
+ 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",
+ )
self.assertEqual(rdata.float_latitude, 30.5)
self.assertEqual(rdata.float_longitude, -100.5)
def test_SOA_BIND8_TTL(self):
- rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
- u"a b 100 1s 1m 1h 1d")
- rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
- u"a b 100 1 60 3600 86400")
+ rdata1 = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.SOA, "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"
+ )
self.assertEqual(rdata1, rdata2)
def test_empty_NSEC3_window(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3,
- u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715")
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.NSEC3,
+ "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715",
+ )
self.assertEqual(rdata.windows, ())
def test_zero_size_APL(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL,
- "")
- rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.APL,
- "", 0, 0)
+ rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, "")
+ rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.APL, "", 0, 0)
self.assertEqual(rdata, rdata2)
def test_CAA_from_wire(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CAA,
- '0 issue "ca.example.net"')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CAA, '0 issue "ca.example.net"'
+ )
f = BytesIO()
rdata.to_wire(f)
wire = f.getvalue()
rdlen = len(wire)
wire += b"trailing garbage"
- rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.CAA,
- wire, 0, rdlen)
+ rdata2 = dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.CAA, wire, 0, rdlen
+ )
self.assertEqual(rdata, rdata2)
def test_trailing_zero_APL(self):
in4 = "!1:127.0.0.0/1"
rd4 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in4)
out4 = rd4.to_digestable(dns.name.from_text("test"))
- text4 = binascii.hexlify(out4).decode('ascii')
- self.assertEqual(text4, '000101817f')
+ text4 = binascii.hexlify(out4).decode("ascii")
+ self.assertEqual(text4, "000101817f")
in6 = "!2:::1000/1"
rd6 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in6)
out6 = rd6.to_digestable(dns.name.from_text("test"))
- text6 = binascii.hexlify(out6).decode('ascii')
- self.assertEqual(text6, '0002018f000000000000000000000000000010')
+ text6 = binascii.hexlify(out6).decode("ascii")
+ self.assertEqual(text6, "0002018f000000000000000000000000000010")
def test_TXT_conversions(self):
- t1 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
- [b'foo'])
- t2 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
- b'foo')
- t3 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
- 'foo')
- t4 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
- ['foo'])
+ t1 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, [b"foo"])
+ t2 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, b"foo")
+ t3 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, "foo")
+ t4 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, ["foo"])
self.assertEqual(t1, t2)
self.assertEqual(t1, t2)
self.assertEqual(t1, t4)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
class ConstantsTestCase(unittest.TestCase):
-
def test_dnssec_constants(self):
- tests.util.check_enum_exports(dns.dnssec, self.assertEqual,
- only={dns.dnssec.Algorithm})
+ tests.util.check_enum_exports(
+ dns.dnssec, self.assertEqual, only={dns.dnssec.Algorithm}
+ )
tests.util.check_enum_exports(dns.rdtypes.dnskeybase, self.assertEqual)
def test_flags_constants(self):
tests.util.check_enum_exports(dns.rdatatype, self.assertEqual)
def test_edns_constants(self):
- tests.util.check_enum_exports(dns.edns, self.assertEqual,
- only={dns.edns.OptionType})
+ tests.util.check_enum_exports(
+ dns.edns, self.assertEqual, only={dns.edns.OptionType}
+ )
# pylint: disable=line-too-long
-abs_dnspython_org = dns.name.from_text('dnspython.org')
+abs_dnspython_org = dns.name.from_text("dnspython.org")
abs_keys = {
abs_dnspython_org: dns.rrset.from_text(
- 'dnspython.org.', 3600, 'IN', 'DNSKEY',
- '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=',
- '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF'
+ "dnspython.org.",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=",
+ "256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF",
)
}
abs_keys_duplicate_keytag = {
abs_dnspython_org: dns.rrset.from_text(
- 'dnspython.org.', 3600, 'IN', 'DNSKEY',
- '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=',
- '256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF',
- '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF'
+ "dnspython.org.",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=",
+ "256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF",
+ "256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF",
)
}
rel_keys = {
dns.name.empty: dns.rrset.from_text(
- '@', 3600, 'IN', 'DNSKEY',
- '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=',
- '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF'
+ "@",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=",
+ "256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF",
)
}
when = 1290250287
-abs_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA',
- 'howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600')
-
-abs_other_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA',
- 'foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600')
-
-abs_soa_rrsig = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'RRSIG',
- 'SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=')
-
-rel_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA',
- 'howl hostmaster 2010020047 3600 1800 604800 3600')
-
-rel_other_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA',
- 'foo hostmaster 2010020047 3600 1800 604800 3600')
-
-rel_soa_rrsig = dns.rrset.from_text('@', 3600, 'IN', 'RRSIG',
- 'SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=')
-
-sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY,
- '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=')
-
-good_ds = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS,
- '57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013')
+abs_soa = dns.rrset.from_text(
+ "dnspython.org.",
+ 3600,
+ "IN",
+ "SOA",
+ "howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600",
+)
+
+abs_other_soa = dns.rrset.from_text(
+ "dnspython.org.",
+ 3600,
+ "IN",
+ "SOA",
+ "foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600",
+)
+
+abs_soa_rrsig = dns.rrset.from_text(
+ "dnspython.org.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=",
+)
+
+rel_soa = dns.rrset.from_text(
+ "@", 3600, "IN", "SOA", "howl hostmaster 2010020047 3600 1800 604800 3600"
+)
+
+rel_other_soa = dns.rrset.from_text(
+ "@", 3600, "IN", "SOA", "foo hostmaster 2010020047 3600 1800 604800 3600"
+)
+
+rel_soa_rrsig = dns.rrset.from_text(
+ "@",
+ 3600,
+ "IN",
+ "RRSIG",
+ "SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=",
+)
+
+sep_key = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DNSKEY,
+ "257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=",
+)
+
+good_ds = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ "57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013",
+)
when2 = 1290425644
-abs_example = dns.name.from_text('example')
+abs_example = dns.name.from_text("example")
abs_dsa_keys = {
abs_example: dns.rrset.from_text(
- 'example.', 86400, 'IN', 'DNSKEY',
- '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X',
- '256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B'
+ "example.",
+ 86400,
+ "IN",
+ "DNSKEY",
+ "257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X",
+ "256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B",
)
}
-abs_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400')
-
-abs_other_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401')
-
-abs_dsa_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG',
- 'SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=')
-
-example_sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY,
- '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X')
-
-example_ds_sha1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS,
- '18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7')
-
-example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS,
- '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913')
-
-example_ds_sha384 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS,
- '18673 3 4 61ab241025c5f88d2537be04dcfba96f952adaefe0b382ecbc4108c97b75768c9e99fd16caed2a09634c51e8089fb84f')
+abs_dsa_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 2 10800 3600 604800 86400",
+)
+
+abs_other_dsa_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 2 10800 3600 604800 86401",
+)
+
+abs_dsa_soa_rrsig = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "RRSIG",
+ "SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=",
+)
+
+example_sep_key = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DNSKEY,
+ "257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X",
+)
+
+example_ds_sha1 = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ "18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7",
+)
+
+example_ds_sha256 = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ "18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913",
+)
+
+example_ds_sha384 = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ "18673 3 4 61ab241025c5f88d2537be04dcfba96f952adaefe0b382ecbc4108c97b75768c9e99fd16caed2a09634c51e8089fb84f",
+)
when3 = 1379801800
abs_ecdsa256_keys = {
abs_example: dns.rrset.from_text(
- 'example.', 86400, 'IN', 'DNSKEY',
+ "example.",
+ 86400,
+ "IN",
+ "DNSKEY",
"256 3 13 +3ss1sCpdARVA61DJigEsL/8quo2a8MszKtn2gkkfxgzFs8S2UHtpb4N fY+XFmNW+JK6MsCkI3jHYN8eEQUgMw==",
- "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ=="
+ "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ==",
)
}
-abs_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 4 10800 3600 604800 86400')
-
-abs_other_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401')
-
-abs_ecdsa256_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG',
- "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==")
+abs_ecdsa256_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 4 10800 3600 604800 86400",
+)
+
+abs_other_ecdsa256_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 2 10800 3600 604800 86401",
+)
+
+abs_ecdsa256_soa_rrsig = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "RRSIG",
+ "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==",
+)
when4 = 1379804850
abs_ecdsa384_keys = {
abs_example: dns.rrset.from_text(
- 'example.', 86400, 'IN', 'DNSKEY',
+ "example.",
+ 86400,
+ "IN",
+ "DNSKEY",
"256 3 14 1bG8qWviKNXQX3BIuG6/T5jrP1FISiLW/8qGF6BsM9DQtWYhhZUA3Owr OAEiyHAhQwjkN2kTvWiAYoPN80Ii+5ff9/atzY4F9W50P4l75Dj9PYrL HN/hLUgWMNVc9pvA",
- "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9"
+ "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9",
)
}
-abs_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400')
-
-abs_other_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA',
- 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401')
-
-abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG',
- "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI")
-
-abs_example_com = dns.name.from_text('example.com')
-
-abs_ed25519_mx = dns.rrset.from_text('example.com.', 3600, 'IN', 'MX',
- '10 mail.example.com.')
-abs_other_ed25519_mx = dns.rrset.from_text('example.com.', 3600, 'IN', 'MX',
- '11 mail.example.com.')
+abs_ecdsa384_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 2 10800 3600 604800 86400",
+)
+
+abs_other_ecdsa384_soa = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "SOA",
+ "ns1.example. hostmaster.example. 2 10800 3600 604800 86401",
+)
+
+abs_ecdsa384_soa_rrsig = dns.rrset.from_text(
+ "example.",
+ 86400,
+ "IN",
+ "RRSIG",
+ "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI",
+)
+
+abs_example_com = dns.name.from_text("example.com")
+
+abs_ed25519_mx = dns.rrset.from_text(
+ "example.com.", 3600, "IN", "MX", "10 mail.example.com."
+)
+abs_other_ed25519_mx = dns.rrset.from_text(
+ "example.com.", 3600, "IN", "MX", "11 mail.example.com."
+)
abs_ed25519_keys_1 = {
abs_example_com: dns.rrset.from_text(
- 'example.com', 3600, 'IN', 'DNSKEY',
- '257 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=')
+ "example.com",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=",
+ )
}
-abs_ed25519_mx_rrsig_1 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG',
- 'MX 15 2 3600 1440021600 1438207200 3613 example.com. oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==')
+abs_ed25519_mx_rrsig_1 = dns.rrset.from_text(
+ "example.com.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "MX 15 2 3600 1440021600 1438207200 3613 example.com. oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==",
+)
abs_ed25519_keys_2 = {
abs_example_com: dns.rrset.from_text(
- 'example.com', 3600, 'IN', 'DNSKEY',
- '257 3 15 zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs=')
+ "example.com",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 15 zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs=",
+ )
}
-abs_ed25519_mx_rrsig_2 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG',
- 'MX 15 2 3600 1440021600 1438207200 35217 example.com. zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQoSm5poJ7gD7AQR0O7KuI5k2pcBg==')
+abs_ed25519_mx_rrsig_2 = dns.rrset.from_text(
+ "example.com.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "MX 15 2 3600 1440021600 1438207200 35217 example.com. zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQoSm5poJ7gD7AQR0O7KuI5k2pcBg==",
+)
abs_ed448_mx = abs_ed25519_mx
abs_other_ed448_mx = abs_other_ed25519_mx
abs_ed448_keys_1 = {
abs_example_com: dns.rrset.from_text(
- 'example.com', 3600, 'IN', 'DNSKEY',
- '257 3 16 3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA')
+ "example.com",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 16 3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA",
+ )
}
-abs_ed448_mx_rrsig_1 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG',
- 'MX 16 2 3600 1440021600 1438207200 9713 example.com. 3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA')
+abs_ed448_mx_rrsig_1 = dns.rrset.from_text(
+ "example.com.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "MX 16 2 3600 1440021600 1438207200 9713 example.com. 3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA",
+)
abs_ed448_keys_2 = {
abs_example_com: dns.rrset.from_text(
- 'example.com', 3600, 'IN', 'DNSKEY',
- '257 3 16 kkreGWoccSDmUBGAe7+zsbG6ZAFQp+syPmYUurBRQc3tDjeMCJcVMRDmgcNLp5HlHAMy12VoISsA')
+ "example.com",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "257 3 16 kkreGWoccSDmUBGAe7+zsbG6ZAFQp+syPmYUurBRQc3tDjeMCJcVMRDmgcNLp5HlHAMy12VoISsA",
+ )
}
-abs_ed448_mx_rrsig_2 = dns.rrset.from_text('example.com.', 3600, 'IN', 'RRSIG',
- 'MX 16 2 3600 1440021600 1438207200 38353 example.com. E1/oLjSGIbmLny/4fcgM1z4oL6aqo+izT3urCyHyvEp4Sp8Syg1eI+lJ57CSnZqjJP41O/9l4m0AsQ4f7qI1gVnML8vWWiyW2KXhT9kuAICUSxv5OWbf81Rq7Yu60npabODB0QFPb/rkW3kUZmQ0YQUA')
+abs_ed448_mx_rrsig_2 = dns.rrset.from_text(
+ "example.com.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "MX 16 2 3600 1440021600 1438207200 38353 example.com. E1/oLjSGIbmLny/4fcgM1z4oL6aqo+izT3urCyHyvEp4Sp8Syg1eI+lJ57CSnZqjJP41O/9l4m0AsQ4f7qI1gVnML8vWWiyW2KXhT9kuAICUSxv5OWbf81Rq7Yu60npabODB0QFPb/rkW3kUZmQ0YQUA",
+)
when5 = 1440021600
when5_start = 1438207200
wildcard_keys = {
- abs_example_com : dns.rrset.from_text(
- 'example.com', 3600, 'IN', 'DNSKEY',
- '256 3 5 AwEAAecNZbwD2thg3kaRLVqCC7ASP/3F79ZIu7pCu8HvZZ6ZdinffnxT npNoVvavjouHKFYTtJyUZAfw3ZMJSsGvEerc7uh6Ex9TgvOJtWPGUtxB Nnni2u9Nk+5k6nJzMiS3sL3RLvrfZW5d2Bwbl9L5f9Ud+r2Dbm7EG3tY pMY5OE8f')
+ abs_example_com: dns.rrset.from_text(
+ "example.com",
+ 3600,
+ "IN",
+ "DNSKEY",
+ "256 3 5 AwEAAecNZbwD2thg3kaRLVqCC7ASP/3F79ZIu7pCu8HvZZ6ZdinffnxT npNoVvavjouHKFYTtJyUZAfw3ZMJSsGvEerc7uh6Ex9TgvOJtWPGUtxB Nnni2u9Nk+5k6nJzMiS3sL3RLvrfZW5d2Bwbl9L5f9Ud+r2Dbm7EG3tY pMY5OE8f",
+ )
}
-wildcard_example_com = dns.name.from_text('*', abs_example_com)
-wildcard_txt = dns.rrset.from_text('*.example.com.', 3600, 'IN', 'TXT', 'foo')
-wildcard_txt_rrsig = dns.rrset.from_text('*.example.com.', 3600, 'IN', 'RRSIG',
- 'TXT 5 2 3600 20200707211255 20200630180755 42486 example.com. qevJYhdAHq1VmehXQ5i+Epa32xs4zcd4qmb39pHa3GUKr1V504nxzdzQ gsT5mvDkRoY95+HAiysDON6DCDtZc69iBUIHWWuFo/OrcD2q/mWANG4x vyU28Pf0U1gN6Gd5iapKC0Ya12flKh//NQiNN2skOQ2MoF2MW2/MaAK2 HBc=')
+wildcard_example_com = dns.name.from_text("*", abs_example_com)
+wildcard_txt = dns.rrset.from_text("*.example.com.", 3600, "IN", "TXT", "foo")
+wildcard_txt_rrsig = dns.rrset.from_text(
+ "*.example.com.",
+ 3600,
+ "IN",
+ "RRSIG",
+ "TXT 5 2 3600 20200707211255 20200630180755 42486 example.com. qevJYhdAHq1VmehXQ5i+Epa32xs4zcd4qmb39pHa3GUKr1V504nxzdzQ gsT5mvDkRoY95+HAiysDON6DCDtZc69iBUIHWWuFo/OrcD2q/mWANG4x vyU28Pf0U1gN6Gd5iapKC0Ya12flKh//NQiNN2skOQ2MoF2MW2/MaAK2 HBc=",
+)
wildcard_when = 1593541048
rsamd5_keys = {
abs_example: dns.rrset.from_text(
- 'example', 3600, 'in', 'dnskey',
- '257 3 1 AwEAAewnoEWe+AVEnQzcZTwpl8K/QKuScYIX 9xHOhejAL1enMjE0j97Gq3XXJJPWF7eQQGHs 1De4Srv2UT0zRCLkH9r36lOR/ggANvthO/Ub Es0hlD3A58LumEPudgIDwEkxGvQAXMFTMw0x 1d/a82UtzmNoPVzFOl2r+OCXx9Jbdh/L; KSK; alg = RSAMD5; key id = 30239',
- '256 3 1 AwEAAb8OJM5YcqaYG0fenUdRlrhBQ6LuwCvr 5BRlrVbVzadSDBpq+yIiklfdGNBg3WZztDy1 du62NWC/olMfc6uRe/SjqTa7IJ3MdEuZQXQw MedGdNSF73zbokx8wg7zBBr74xHczJcEpQhr ZLzwCDmIPu0yoVi3Yqdl4dm4vNBj9hAD; ZSK; alg = RSAMD5; key id = 62992')
+ "example",
+ 3600,
+ "in",
+ "dnskey",
+ "257 3 1 AwEAAewnoEWe+AVEnQzcZTwpl8K/QKuScYIX 9xHOhejAL1enMjE0j97Gq3XXJJPWF7eQQGHs 1De4Srv2UT0zRCLkH9r36lOR/ggANvthO/Ub Es0hlD3A58LumEPudgIDwEkxGvQAXMFTMw0x 1d/a82UtzmNoPVzFOl2r+OCXx9Jbdh/L; KSK; alg = RSAMD5; key id = 30239",
+ "256 3 1 AwEAAb8OJM5YcqaYG0fenUdRlrhBQ6LuwCvr 5BRlrVbVzadSDBpq+yIiklfdGNBg3WZztDy1 du62NWC/olMfc6uRe/SjqTa7IJ3MdEuZQXQw MedGdNSF73zbokx8wg7zBBr74xHczJcEpQhr ZLzwCDmIPu0yoVi3Yqdl4dm4vNBj9hAD; ZSK; alg = RSAMD5; key id = 62992",
+ )
}
-rsamd5_ns = dns.rrset.from_text('example.', 3600, 'in', 'ns',
- 'ns1.example.', 'ns2.example.')
-rsamd5_ns_rrsig = dns.rrset.from_text('example.', 3600, 'in', 'rrsig',
- 'NS 1 1 3600 20200825153103 20200726153103 62992 example. YPv0WVqzQBDH45mFcYGo9psCVoMoeeHeAugh 9RZuO2NmdwfQ3mmiQm7WJ3AYnzYIozFGf7CL nwn3vN8/fjsfcQgEv5xfhFTSd4IoAzJJiZAa vrI4L5590C/+aXQ8tjRmbMTPiqoudaXvsevE jP2lTFg5DCruJyFq5dnAY5b90RY=')
+rsamd5_ns = dns.rrset.from_text(
+ "example.", 3600, "in", "ns", "ns1.example.", "ns2.example."
+)
+rsamd5_ns_rrsig = dns.rrset.from_text(
+ "example.",
+ 3600,
+ "in",
+ "rrsig",
+ "NS 1 1 3600 20200825153103 20200726153103 62992 example. YPv0WVqzQBDH45mFcYGo9psCVoMoeeHeAugh 9RZuO2NmdwfQ3mmiQm7WJ3AYnzYIozFGf7CL nwn3vN8/fjsfcQgEv5xfhFTSd4IoAzJJiZAa vrI4L5590C/+aXQ8tjRmbMTPiqoudaXvsevE jP2lTFg5DCruJyFq5dnAY5b90RY=",
+)
rsamd5_when = 1595781671
rsasha512_keys = {
abs_example: dns.rrset.from_text(
- 'example', 3600, 'in', 'dnskey',
- '256 3 10 AwEAAb2JvKjZ6l5qg2ab3qqUQhLGGjsiMIuQ 2zhaXJHdTntS+8LgUXo5yLFn7YF9YL1VX9V4 5ASGxUpz0u0chjWqBNtUO3Ymzas/vck9o21M 2Ce/LrpfYsqvJaLvGf/dozW9uSeMQq1mPKYG xo4uxyhZBhZewX8znXZySrAIozBPH3yp ; ZSK; alg = RSASHA512 ; key id = 5957',
- '257 3 10 AwEAAc7Lnoe+mHijJ8OOHgyJHKYantQGKx5t rIs267gOePyAL7cUt9HO1Sm3vABSGNsoHL6w 8/542SxGbT21osVISamtq7kUPTgDU9iKqCBq VdXEdzXYbhBKVoQkGPl4PflfbOgg/45xAiTi 7qOUERuRCPdKEkd4FW0tg6VfZmm7QjP1 ; KSK; alg = RSASHA512 ; key id = 53212')
+ "example",
+ 3600,
+ "in",
+ "dnskey",
+ "256 3 10 AwEAAb2JvKjZ6l5qg2ab3qqUQhLGGjsiMIuQ 2zhaXJHdTntS+8LgUXo5yLFn7YF9YL1VX9V4 5ASGxUpz0u0chjWqBNtUO3Ymzas/vck9o21M 2Ce/LrpfYsqvJaLvGf/dozW9uSeMQq1mPKYG xo4uxyhZBhZewX8znXZySrAIozBPH3yp ; ZSK; alg = RSASHA512 ; key id = 5957",
+ "257 3 10 AwEAAc7Lnoe+mHijJ8OOHgyJHKYantQGKx5t rIs267gOePyAL7cUt9HO1Sm3vABSGNsoHL6w 8/542SxGbT21osVISamtq7kUPTgDU9iKqCBq VdXEdzXYbhBKVoQkGPl4PflfbOgg/45xAiTi 7qOUERuRCPdKEkd4FW0tg6VfZmm7QjP1 ; KSK; alg = RSASHA512 ; key id = 53212",
+ )
}
-rsasha512_ns = dns.rrset.from_text('example.', 3600, 'in', 'ns',
- 'ns1.example.', 'ns2.example.')
+rsasha512_ns = dns.rrset.from_text(
+ "example.", 3600, "in", "ns", "ns1.example.", "ns2.example."
+)
rsasha512_ns_rrsig = dns.rrset.from_text(
- 'example.', 3600, 'in', 'rrsig',
- 'NS 10 1 3600 20200825161255 20200726161255 5957 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=')
+ "example.",
+ 3600,
+ "in",
+ "rrsig",
+ "NS 10 1 3600 20200825161255 20200726161255 5957 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=",
+)
rsasha512_when = 1595783997
unknown_alg_keys = {
abs_example: dns.rrset.from_text(
- 'example', 3600, 'in', 'dnskey',
- '256 3 100 Ym9ndXM=',
- '257 3 100 Ym9ndXM=')
+ "example", 3600, "in", "dnskey", "256 3 100 Ym9ndXM=", "257 3 100 Ym9ndXM="
+ )
}
unknown_alg_ns_rrsig = dns.rrset.from_text(
- 'example.', 3600, 'in', 'rrsig',
- 'NS 100 1 3600 20200825161255 20200726161255 16713 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=')
+ "example.",
+ 3600,
+ "in",
+ "rrsig",
+ "NS 100 1 3600 20200825161255 20200726161255 16713 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=",
+)
fake_gost_keys = {
abs_example: dns.rrset.from_text(
- 'example', 3600, 'in', 'dnskey',
- '256 3 12 Ym9ndXM=',
- '257 3 12 Ym9ndXM=')
+ "example", 3600, "in", "dnskey", "256 3 12 Ym9ndXM=", "257 3 12 Ym9ndXM="
+ )
}
fake_gost_ns_rrsig = dns.rrset.from_text(
- 'example.', 3600, 'in', 'rrsig',
- 'NS 12 1 3600 20200825161255 20200726161255 16625 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=')
+ "example.",
+ 3600,
+ "in",
+ "rrsig",
+ "NS 12 1 3600 20200825161255 20200726161255 16625 example. P9A+1zYke7yIiKEnxFMm+UIW2CIwy2WDvbx6 g8hHiI8qISe6oeKveFW23OSk9+VwFgBiOpeM ygzzFbckY7RkGbOr4TR8ogDRANt6LhV402Hu SXTV9hCLVFWU4PS+/fxxfOHCetsY5tWWSxZi zSHfgpGfsHWzQoAamag4XYDyykc=",
+)
-@unittest.skipUnless(dns.dnssec._have_pyca,
- "Python Cryptography cannot be imported")
-class DNSSECValidatorTestCase(unittest.TestCase):
+@unittest.skipUnless(dns.dnssec._have_pyca, "Python Cryptography cannot be imported")
+class DNSSECValidatorTestCase(unittest.TestCase):
def testAbsoluteRSAMD5Good(self): # type: () -> None
- dns.dnssec.validate(rsamd5_ns, rsamd5_ns_rrsig, rsamd5_keys, None,
- rsamd5_when)
+ dns.dnssec.validate(rsamd5_ns, rsamd5_ns_rrsig, rsamd5_keys, None, rsamd5_when)
def testRSAMD5Keyid(self):
self.assertEqual(dns.dnssec.key_id(rsamd5_keys[abs_example][0]), 30239)
dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when)
def testDuplicateKeytag(self): # type: () -> None
- dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when)
+ dns.dnssec.validate(
+ abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when
+ )
def testAbsoluteRSABad(self): # type: () -> None
def bad(): # type: () -> None
- dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None,
- when)
+ dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, when)
+
self.assertRaises(dns.dnssec.ValidationFailure, bad)
def testRelativeRSAGood(self): # type: () -> None
- dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys,
- abs_dnspython_org, when)
+ dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, abs_dnspython_org, when)
# test the text conversion for origin too
- dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys,
- 'dnspython.org', when)
+ dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, "dnspython.org", when)
def testRelativeRSABad(self): # type: () -> None
def bad(): # type: () -> None
- dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys,
- abs_dnspython_org, when)
+ dns.dnssec.validate(
+ rel_other_soa, rel_soa_rrsig, rel_keys, abs_dnspython_org, when
+ )
+
self.assertRaises(dns.dnssec.ValidationFailure, bad)
def testAbsoluteDSAGood(self): # type: () -> None
- dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None,
- when2)
+ dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, when2)
def testAbsoluteDSABad(self): # type: () -> None
def bad(): # type: () -> None
- dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig,
- abs_dsa_keys, None, when2)
+ dns.dnssec.validate(
+ abs_other_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, when2
+ )
+
self.assertRaises(dns.dnssec.ValidationFailure, bad)
def testAbsoluteECDSA256Good(self): # type: () -> None
- dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig,
- abs_ecdsa256_keys, None, when3)
+ dns.dnssec.validate(
+ abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, abs_ecdsa256_keys, None, when3
+ )
def testAbsoluteECDSA256Bad(self): # type: () -> None
def bad(): # type: () -> None
- dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig,
- abs_ecdsa256_keys, None, when3)
+ dns.dnssec.validate(
+ abs_other_ecdsa256_soa,
+ abs_ecdsa256_soa_rrsig,
+ abs_ecdsa256_keys,
+ None,
+ when3,
+ )
+
self.assertRaises(dns.dnssec.ValidationFailure, bad)
def testAbsoluteECDSA384Good(self): # type: () -> None
- dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig,
- abs_ecdsa384_keys, None, when4)
+ dns.dnssec.validate(
+ abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, abs_ecdsa384_keys, None, when4
+ )
def testAbsoluteECDSA384Bad(self): # type: () -> None
def bad(): # type: () -> None
- dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig,
- abs_ecdsa384_keys, None, when4)
+ dns.dnssec.validate(
+ abs_other_ecdsa384_soa,
+ abs_ecdsa384_soa_rrsig,
+ abs_ecdsa384_keys,
+ None,
+ when4,
+ )
+
self.assertRaises(dns.dnssec.ValidationFailure, bad)
def testAbsoluteED25519Good(self): # type: () -> None
- dns.dnssec.validate(abs_ed25519_mx, abs_ed25519_mx_rrsig_1,
- abs_ed25519_keys_1, None, when5)
- dns.dnssec.validate(abs_ed25519_mx, abs_ed25519_mx_rrsig_2,
- abs_ed25519_keys_2, None, when5)
+ dns.dnssec.validate(
+ abs_ed25519_mx, abs_ed25519_mx_rrsig_1, abs_ed25519_keys_1, None, when5
+ )
+ dns.dnssec.validate(
+ abs_ed25519_mx, abs_ed25519_mx_rrsig_2, abs_ed25519_keys_2, None, when5
+ )
def testAbsoluteED25519Bad(self): # type: () -> None
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_other_ed25519_mx, abs_ed25519_mx_rrsig_1,
- abs_ed25519_keys_1, None, when5)
+ dns.dnssec.validate(
+ abs_other_ed25519_mx,
+ abs_ed25519_mx_rrsig_1,
+ abs_ed25519_keys_1,
+ None,
+ when5,
+ )
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_other_ed25519_mx, abs_ed25519_mx_rrsig_2,
- abs_ed25519_keys_2, None, when5)
+ dns.dnssec.validate(
+ abs_other_ed25519_mx,
+ abs_ed25519_mx_rrsig_2,
+ abs_ed25519_keys_2,
+ None,
+ when5,
+ )
def testAbsoluteED448Good(self): # type: () -> None
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None, when5)
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_2,
- abs_ed448_keys_2, None, when5)
+ dns.dnssec.validate(
+ abs_ed448_mx, abs_ed448_mx_rrsig_1, abs_ed448_keys_1, None, when5
+ )
+ dns.dnssec.validate(
+ abs_ed448_mx, abs_ed448_mx_rrsig_2, abs_ed448_keys_2, None, when5
+ )
def testAbsoluteED448Bad(self): # type: () -> None
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_other_ed448_mx, abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None, when5)
+ dns.dnssec.validate(
+ abs_other_ed448_mx, abs_ed448_mx_rrsig_1, abs_ed448_keys_1, None, when5
+ )
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_other_ed448_mx, abs_ed448_mx_rrsig_2,
- abs_ed448_keys_2, None, when5)
+ dns.dnssec.validate(
+ abs_other_ed448_mx, abs_ed448_mx_rrsig_2, abs_ed448_keys_2, None, when5
+ )
def testAbsoluteRSASHA512Good(self):
- dns.dnssec.validate(rsasha512_ns, rsasha512_ns_rrsig, rsasha512_keys,
- None, rsasha512_when)
+ dns.dnssec.validate(
+ rsasha512_ns, rsasha512_ns_rrsig, rsasha512_keys, None, rsasha512_when
+ )
def testWildcardGoodAndBad(self):
- dns.dnssec.validate(wildcard_txt, wildcard_txt_rrsig,
- wildcard_keys, None, wildcard_when)
+ dns.dnssec.validate(
+ wildcard_txt, wildcard_txt_rrsig, wildcard_keys, None, wildcard_when
+ )
def clone_rrset(rrset, name):
return dns.rrset.from_rdata(name, rrset.ttl, rrset[0])
- a_name = dns.name.from_text('a.example.com')
+ a_name = dns.name.from_text("a.example.com")
a_txt = clone_rrset(wildcard_txt, a_name)
a_txt_rrsig = clone_rrset(wildcard_txt_rrsig, a_name)
- dns.dnssec.validate(a_txt, a_txt_rrsig, wildcard_keys, None,
- wildcard_when)
+ dns.dnssec.validate(a_txt, a_txt_rrsig, wildcard_keys, None, wildcard_when)
- abc_name = dns.name.from_text('a.b.c.example.com')
+ abc_name = dns.name.from_text("a.b.c.example.com")
abc_txt = clone_rrset(wildcard_txt, abc_name)
abc_txt_rrsig = clone_rrset(wildcard_txt_rrsig, abc_name)
- dns.dnssec.validate(abc_txt, abc_txt_rrsig, wildcard_keys, None,
- wildcard_when)
+ dns.dnssec.validate(abc_txt, abc_txt_rrsig, wildcard_keys, None, wildcard_when)
- com_name = dns.name.from_text('com.')
+ com_name = dns.name.from_text("com.")
com_txt = clone_rrset(wildcard_txt, com_name)
com_txt_rrsig = clone_rrset(wildcard_txt_rrsig, abc_name)
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate_rrsig(com_txt, com_txt_rrsig[0], wildcard_keys,
- None, wildcard_when)
+ dns.dnssec.validate_rrsig(
+ com_txt, com_txt_rrsig[0], wildcard_keys, None, wildcard_when
+ )
def testAlternateParameterFormats(self): # type: () -> None
# Pass rrset and rrsigset as (name, rdataset) tuples, not rrsets
dns.dnssec.validate(abs_soa, abs_soa_rrsig, keys, None, when)
# Pass origin as a string, not a name.
- dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys,
- 'dnspython.org', when)
- dns.dnssec.validate_rrsig(rel_soa, rel_soa_rrsig[0], rel_keys,
- 'dnspython.org', when)
+ dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, "dnspython.org", when)
+ dns.dnssec.validate_rrsig(
+ rel_soa, rel_soa_rrsig[0], rel_keys, "dnspython.org", when
+ )
def testAbsoluteKeyNotFound(self):
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, {}, None,
- when5)
+ dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1, {}, None, when5)
def testTimeBounds(self):
# not yet valid
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None, when5_start - 1)
+ dns.dnssec.validate(
+ abs_ed448_mx,
+ abs_ed448_mx_rrsig_1,
+ abs_ed448_keys_1,
+ None,
+ when5_start - 1,
+ )
# expired
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None, when5 + 1)
+ dns.dnssec.validate(
+ abs_ed448_mx, abs_ed448_mx_rrsig_1, abs_ed448_keys_1, None, when5 + 1
+ )
# expired using the current time (to test the "get the time" code
# path)
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(abs_ed448_mx, abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None)
+ dns.dnssec.validate(
+ abs_ed448_mx, abs_ed448_mx_rrsig_1, abs_ed448_keys_1, None
+ )
def testOwnerNameMismatch(self):
- bogus = dns.name.from_text('example.bogus')
+ bogus = dns.name.from_text("example.bogus")
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate((bogus, abs_ed448_mx), abs_ed448_mx_rrsig_1,
- abs_ed448_keys_1, None, when5 + 1)
+ dns.dnssec.validate(
+ (bogus, abs_ed448_mx),
+ abs_ed448_mx_rrsig_1,
+ abs_ed448_keys_1,
+ None,
+ when5 + 1,
+ )
def testGOSTNotSupported(self):
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(rsasha512_ns, fake_gost_ns_rrsig,
- fake_gost_keys, None, rsasha512_when)
+ dns.dnssec.validate(
+ rsasha512_ns, fake_gost_ns_rrsig, fake_gost_keys, None, rsasha512_when
+ )
def testUnknownAlgorithm(self):
with self.assertRaises(dns.dnssec.ValidationFailure):
- dns.dnssec.validate(rsasha512_ns, unknown_alg_ns_rrsig,
- unknown_alg_keys, None, rsasha512_when)
+ dns.dnssec.validate(
+ rsasha512_ns,
+ unknown_alg_ns_rrsig,
+ unknown_alg_keys,
+ None,
+ rsasha512_when,
+ )
class DNSSECMiscTestCase(unittest.TestCase):
class DNSSECMakeDSTestCase(unittest.TestCase):
-
def testMnemonicParser(self):
- good_ds_mnemonic = dns.rdata.from_text(dns.rdataclass.IN,
- dns.rdatatype.DS,
- '57349 RSASHA1 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013')
+ good_ds_mnemonic = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ "57349 RSASHA1 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013",
+ )
self.assertEqual(good_ds, good_ds_mnemonic)
def testMakeExampleSHA1DS(self): # type: () -> None
algorithm: Any
- for algorithm in ('SHA1', 'sha1', dns.dnssec.DSDigest.SHA1):
+ for algorithm in ("SHA1", "sha1", dns.dnssec.DSDigest.SHA1):
ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm)
self.assertEqual(ds, example_ds_sha1)
- ds = dns.dnssec.make_ds('example.', example_sep_key, algorithm)
+ ds = dns.dnssec.make_ds("example.", example_sep_key, algorithm)
self.assertEqual(ds, example_ds_sha1)
def testMakeExampleSHA256DS(self): # type: () -> None
algorithm: Any
- for algorithm in ('SHA256', 'sha256', dns.dnssec.DSDigest.SHA256):
+ for algorithm in ("SHA256", "sha256", dns.dnssec.DSDigest.SHA256):
ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm)
self.assertEqual(ds, example_ds_sha256)
def testMakeExampleSHA384DS(self): # type: () -> None
algorithm: Any
- for algorithm in ('SHA384', 'sha384', dns.dnssec.DSDigest.SHA384):
+ for algorithm in ("SHA384", "sha384", dns.dnssec.DSDigest.SHA384):
ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm)
self.assertEqual(ds, example_ds_sha384)
def testMakeSHA256DS(self): # type: () -> None
- ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256')
+ ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, "SHA256")
self.assertEqual(ds, good_ds)
def testInvalidAlgorithm(self): # type: () -> None
algorithm: Any
- for algorithm in (10, 'shax'):
+ for algorithm in (10, "shax"):
with self.assertRaises(dns.dnssec.UnsupportedAlgorithm):
ds = dns.dnssec.make_ds(abs_example, example_sep_key, algorithm)
def testReservedDigestType(self): # type: () -> None
with self.assertRaises(dns.exception.SyntaxError) as cm:
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS,
- f'18673 3 0 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7')
- self.assertEqual('digest type 0 is reserved', str(cm.exception))
+ dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ f"18673 3 0 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7",
+ )
+ self.assertEqual("digest type 0 is reserved", str(cm.exception))
def testUnknownDigestType(self): # type: () -> None
digest_types = [dns.rdatatype.DS, dns.rdatatype.CDS]
for rdtype in digest_types:
- rd = dns.rdata.from_text(dns.rdataclass.IN, rdtype,
- f'18673 3 5 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7')
- assert isinstance(rd, dns.rdtypes.ANY.DS.DS) or isinstance(rd, dns.rdtypes.ANY.CDS.CDS)
+ rd = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ rdtype,
+ f"18673 3 5 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7",
+ )
+ assert isinstance(rd, dns.rdtypes.ANY.DS.DS) or isinstance(
+ rd, dns.rdtypes.ANY.CDS.CDS
+ )
self.assertEqual(rd.digest_type, 5)
- self.assertEqual(rd.digest, bytes.fromhex('71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7'))
+ self.assertEqual(
+ rd.digest, bytes.fromhex("71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7")
+ )
def testInvalidDigestLength(self): # type: () -> None
test_records = []
for rdata in [example_ds_sha1, example_ds_sha256, example_ds_sha384]:
- flags, digest = rdata.to_text().rsplit(' ', 1)
+ flags, digest = rdata.to_text().rsplit(" ", 1)
# Make sure the construction is working
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, f'{flags} {digest}')
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.DS, f"{flags} {digest}"
+ )
- test_records.append(f'{flags} {digest[:len(digest)//2]}') # too short digest
- test_records.append(f'{flags} {digest*2}') # too long digest
+ test_records.append(
+ f"{flags} {digest[:len(digest)//2]}"
+ ) # too short digest
+ test_records.append(f"{flags} {digest*2}") # too long digest
for record in test_records:
with self.assertRaises(dns.exception.SyntaxError) as cm:
dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, record)
- self.assertEqual('digest length inconsistent with digest type', str(cm.exception))
+ self.assertEqual(
+ "digest length inconsistent with digest type", str(cm.exception)
+ )
def testInvalidDigestLengthCDS0(self): # type: () -> None
# Make sure the construction is working
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CDS, f'0 0 0 00')
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CDS, f"0 0 0 00")
test_records = {
- 'expecting another identifier': ['0 0 0', '0 0 0 '],
- 'digest length inconsistent with digest type': ['0 0 0 0000'],
- 'Odd-length string': ['0 0 0 0', '0 0 0 000'],
+ "expecting another identifier": ["0 0 0", "0 0 0 "],
+ "digest length inconsistent with digest type": ["0 0 0 0000"],
+ "Odd-length string": ["0 0 0 0", "0 0 0 000"],
}
for msg, records in test_records.items():
for record in records:
self.assertEqual(msg, str(cm.exception))
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
import unittest
import random
import socket
+
try:
import ssl
+
_have_ssl = True
except Exception:
_have_ssl = False
try:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.settimeout(4)
- s.connect(('8.8.8.8', 53))
+ s.connect(("8.8.8.8", 53))
resolver_v4_addresses = [
- '1.1.1.1',
- '8.8.8.8',
+ "1.1.1.1",
+ "8.8.8.8",
# '9.9.9.9',
]
except Exception:
pass
try:
with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s:
- s.connect(('2001:4860:4860::8888', 53))
+ s.connect(("2001:4860:4860::8888", 53))
resolver_v6_addresses = [
- '2606:4700:4700::1111',
+ "2606:4700:4700::1111",
# Google says 404
# '2001:4860:4860::8888',
# '2620:fe::fe',
except Exception:
pass
-KNOWN_ANYCAST_DOH_RESOLVER_URLS = ['https://cloudflare-dns.com/dns-query',
- 'https://dns.google/dns-query',
- # 'https://dns11.quad9.net/dns-query',
- ]
+KNOWN_ANYCAST_DOH_RESOLVER_URLS = [
+ "https://cloudflare-dns.com/dns-query",
+ "https://dns.google/dns-query",
+ # 'https://dns11.quad9.net/dns-query',
+]
# Some tests require the internet to be available to run, so let's
# skip those if it's not there.
_network_available = True
try:
- socket.gethostbyname('dnspython.org')
+ socket.gethostbyname("dnspython.org")
except socket.gaierror:
_network_available = False
-@unittest.skipUnless(dns.query._have_requests and _network_available,
- "Python requests cannot be imported; no DNS over HTTPS (DOH)")
+@unittest.skipUnless(
+ dns.query._have_requests and _network_available,
+ "Python requests cannot be imported; no DNS over HTTPS (DOH)",
+)
class DNSOverHTTPSTestCaseRequests(unittest.TestCase):
def setUp(self):
self.session = requests.sessions.Session()
def test_get_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, session=self.session, post=False,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_url, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_post_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, session=self.session, post=True,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_url, session=self.session, post=True, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_build_url_from_ip(self):
self.assertTrue(resolver_v4_addresses or resolver_v6_addresses)
if resolver_v4_addresses:
nameserver_ip = random.choice(resolver_v4_addresses)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
# For some reason Google's DNS over HTTPS fails when you POST to
# https://8.8.8.8/dns-query
# So we're just going to do GET requests here
- r = dns.query.https(q, nameserver_ip, session=self.session,
- post=False, timeout=4)
+ r = dns.query.https(
+ q, nameserver_ip, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
if resolver_v6_addresses:
nameserver_ip = random.choice(resolver_v6_addresses)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_ip, session=self.session,
- post=False, timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_ip, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_bootstrap_address(self):
# We test this to see if v4 is available
if resolver_v4_addresses:
- ip = '185.228.168.168'
- invalid_tls_url = 'https://{}/doh/family-filter/'.format(ip)
- valid_tls_url = 'https://doh.cleanbrowsing.org/doh/family-filter/'
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ ip = "185.228.168.168"
+ invalid_tls_url = "https://{}/doh/family-filter/".format(ip)
+ valid_tls_url = "https://doh.cleanbrowsing.org/doh/family-filter/"
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
# make sure CleanBrowsing's IP address will fail TLS certificate
# check
with self.assertRaises(SSLError):
- dns.query.https(q, invalid_tls_url, session=self.session,
- timeout=4)
+ dns.query.https(q, invalid_tls_url, session=self.session, timeout=4)
# use host header
- r = dns.query.https(q, valid_tls_url, session=self.session,
- bootstrap_address=ip, timeout=4)
+ r = dns.query.https(
+ q, valid_tls_url, session=self.session, bootstrap_address=ip, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_new_session(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
r = dns.query.https(q, nameserver_url, timeout=4)
self.assertTrue(q.is_response(r))
def test_resolver(self):
res = dns.resolver.Resolver(configure=False)
- res.nameservers = ['https://dns.google/dns-query']
- answer = res.resolve('dns.google', 'A')
+ res.nameservers = ["https://dns.google/dns-query"]
+ answer = res.resolve("dns.google", "A")
seen = set([rdata.address for rdata in answer])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
-@unittest.skipUnless(dns.query._have_httpx and _network_available and _have_ssl,
- "Python httpx cannot be imported; no DNS over HTTPS (DOH)")
+@unittest.skipUnless(
+ dns.query._have_httpx and _network_available and _have_ssl,
+ "Python httpx cannot be imported; no DNS over HTTPS (DOH)",
+)
class DNSOverHTTPSTestCaseHttpx(unittest.TestCase):
def setUp(self):
self.session = httpx.Client(http1=True, http2=True, verify=True)
def test_get_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, session=self.session, post=False,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_url, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_get_request_http1(self):
try:
dns.query._have_http2 = False
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, session=self.session, post=False,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_url, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
finally:
dns.query._have_http2 = saved_have_http2
def test_post_request(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_url, session=self.session, post=True,
- timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_url, session=self.session, post=True, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_build_url_from_ip(self):
self.assertTrue(resolver_v4_addresses or resolver_v6_addresses)
if resolver_v4_addresses:
nameserver_ip = random.choice(resolver_v4_addresses)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
# For some reason Google's DNS over HTTPS fails when you POST to
# https://8.8.8.8/dns-query
# So we're just going to do GET requests here
- r = dns.query.https(q, nameserver_ip, session=self.session,
- post=False, timeout=4)
+ r = dns.query.https(
+ q, nameserver_ip, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
if resolver_v6_addresses:
nameserver_ip = random.choice(resolver_v6_addresses)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
- r = dns.query.https(q, nameserver_ip, session=self.session,
- post=False, timeout=4)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
+ r = dns.query.https(
+ q, nameserver_ip, session=self.session, post=False, timeout=4
+ )
self.assertTrue(q.is_response(r))
def test_bootstrap_address_fails(self):
# We test this to see if v4 is available
if resolver_v4_addresses:
- ip = '185.228.168.168'
- invalid_tls_url = 'https://{}/doh/family-filter/'.format(ip)
- valid_tls_url = 'https://doh.cleanbrowsing.org/doh/family-filter/'
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ ip = "185.228.168.168"
+ invalid_tls_url = "https://{}/doh/family-filter/".format(ip)
+ valid_tls_url = "https://doh.cleanbrowsing.org/doh/family-filter/"
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
# make sure CleanBrowsing's IP address will fail TLS certificate
# check.
with self.assertRaises(httpx.ConnectError):
- dns.query.https(q, invalid_tls_url, session=self.session,
- timeout=4)
+ dns.query.https(q, invalid_tls_url, session=self.session, timeout=4)
# We can't do the Host header and SNI magic with httpx, but
# we are demanding httpx be used by providing a session, so
# we should get a NoDOH exception.
with self.assertRaises(dns.query.NoDOH):
- dns.query.https(q, valid_tls_url, session=self.session,
- bootstrap_address=ip, timeout=4)
+ dns.query.https(
+ q,
+ valid_tls_url,
+ session=self.session,
+ bootstrap_address=ip,
+ timeout=4,
+ )
def test_new_session(self):
nameserver_url = random.choice(KNOWN_ANYCAST_DOH_RESOLVER_URLS)
- q = dns.message.make_query('example.com.', dns.rdatatype.A)
+ q = dns.message.make_query("example.com.", dns.rdatatype.A)
r = dns.query.https(q, nameserver_url, timeout=4)
self.assertTrue(q.is_response(r))
def test_resolver(self):
res = dns.resolver.Resolver(configure=False)
- res.nameservers = ['https://dns.google/dns-query']
- answer = res.resolve('dns.google', 'A')
+ res.nameservers = ["https://dns.google/dns-query"]
+ answer = res.resolve("dns.google", "A")
seen = set([rdata.address for rdata in answer])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
import dns.edns
import dns.wire
+
class OptionTestCase(unittest.TestCase):
def testGenericOption(self):
- opt = dns.edns.GenericOption(3, b'data')
+ opt = dns.edns.GenericOption(3, b"data")
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'data')
+ self.assertEqual(data, b"data")
self.assertEqual(dns.edns.option_from_wire(3, data, 0, len(data)), opt)
- self.assertEqual(str(opt), 'Generic 3')
+ self.assertEqual(str(opt), "Generic 3")
def testECSOption_prefix_length(self):
- opt = dns.edns.ECSOption('1.2.255.33', 20)
+ opt = dns.edns.ECSOption("1.2.255.33", 20)
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x01\x14\x00\x01\x02\xf0')
+ self.assertEqual(data, b"\x00\x01\x14\x00\x01\x02\xf0")
def testECSOption(self):
- opt = dns.edns.ECSOption('1.2.3.4', 24)
+ opt = dns.edns.ECSOption("1.2.3.4", 24)
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x01\x18\x00\x01\x02\x03')
+ self.assertEqual(data, b"\x00\x01\x18\x00\x01\x02\x03")
# default srclen
- opt = dns.edns.ECSOption('1.2.3.4')
+ opt = dns.edns.ECSOption("1.2.3.4")
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x01\x18\x00\x01\x02\x03')
- self.assertEqual(opt.to_text(), 'ECS 1.2.3.4/24 scope/0')
+ self.assertEqual(data, b"\x00\x01\x18\x00\x01\x02\x03")
+ self.assertEqual(opt.to_text(), "ECS 1.2.3.4/24 scope/0")
def testECSOption25(self):
- opt = dns.edns.ECSOption('1.2.3.255', 25)
+ opt = dns.edns.ECSOption("1.2.3.255", 25)
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x01\x19\x00\x01\x02\x03\x80')
+ self.assertEqual(data, b"\x00\x01\x19\x00\x01\x02\x03\x80")
opt2 = dns.edns.option_from_wire(dns.edns.ECS, data, 0, len(data))
self.assertEqual(opt2.otype, dns.edns.ECS)
- self.assertEqual(opt2.address, '1.2.3.128')
+ self.assertEqual(opt2.address, "1.2.3.128")
self.assertEqual(opt2.srclen, 25)
self.assertEqual(opt2.scopelen, 0)
def testECSOption_v6(self):
- opt = dns.edns.ECSOption('2001:4b98::1')
+ opt = dns.edns.ECSOption("2001:4b98::1")
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x02\x38\x00\x20\x01\x4b\x98\x00\x00\x00')
+ self.assertEqual(data, b"\x00\x02\x38\x00\x20\x01\x4b\x98\x00\x00\x00")
opt2 = dns.edns.option_from_wire(dns.edns.ECS, data, 0, len(data))
self.assertEqual(opt2.otype, dns.edns.ECS)
- self.assertEqual(opt2.address, '2001:4b98::')
+ self.assertEqual(opt2.address, "2001:4b98::")
self.assertEqual(opt2.srclen, 56)
self.assertEqual(opt2.scopelen, 0)
def testECSOption_from_text_valid(self):
- ecs1 = dns.edns.ECSOption.from_text('1.2.3.4/24/0')
- self.assertEqual(ecs1, dns.edns.ECSOption('1.2.3.4', 24, 0))
+ ecs1 = dns.edns.ECSOption.from_text("1.2.3.4/24/0")
+ self.assertEqual(ecs1, dns.edns.ECSOption("1.2.3.4", 24, 0))
- ecs2 = dns.edns.ECSOption.from_text('1.2.3.4/24')
- self.assertEqual(ecs2, dns.edns.ECSOption('1.2.3.4', 24, 0))
+ ecs2 = dns.edns.ECSOption.from_text("1.2.3.4/24")
+ self.assertEqual(ecs2, dns.edns.ECSOption("1.2.3.4", 24, 0))
- ecs3 = dns.edns.ECSOption.from_text('ECS 1.2.3.4/24')
- self.assertEqual(ecs3, dns.edns.ECSOption('1.2.3.4', 24, 0))
+ ecs3 = dns.edns.ECSOption.from_text("ECS 1.2.3.4/24")
+ self.assertEqual(ecs3, dns.edns.ECSOption("1.2.3.4", 24, 0))
- ecs4 = dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32')
- self.assertEqual(ecs4, dns.edns.ECSOption('1.2.3.4', 24, 32))
+ ecs4 = dns.edns.ECSOption.from_text("ECS 1.2.3.4/24/32")
+ self.assertEqual(ecs4, dns.edns.ECSOption("1.2.3.4", 24, 32))
- ecs5 = dns.edns.ECSOption.from_text('2001:4b98::1/64/56')
- self.assertEqual(ecs5, dns.edns.ECSOption('2001:4b98::1', 64, 56))
+ ecs5 = dns.edns.ECSOption.from_text("2001:4b98::1/64/56")
+ self.assertEqual(ecs5, dns.edns.ECSOption("2001:4b98::1", 64, 56))
- ecs6 = dns.edns.ECSOption.from_text('2001:4b98::1/64')
- self.assertEqual(ecs6, dns.edns.ECSOption('2001:4b98::1', 64, 0))
+ ecs6 = dns.edns.ECSOption.from_text("2001:4b98::1/64")
+ self.assertEqual(ecs6, dns.edns.ECSOption("2001:4b98::1", 64, 0))
- ecs7 = dns.edns.ECSOption.from_text('ECS 2001:4b98::1/0')
- self.assertEqual(ecs7, dns.edns.ECSOption('2001:4b98::1', 0, 0))
+ ecs7 = dns.edns.ECSOption.from_text("ECS 2001:4b98::1/0")
+ self.assertEqual(ecs7, dns.edns.ECSOption("2001:4b98::1", 0, 0))
- ecs8 = dns.edns.ECSOption.from_text('ECS 2001:4b98::1/64/128')
- self.assertEqual(ecs8, dns.edns.ECSOption('2001:4b98::1', 64, 128))
+ ecs8 = dns.edns.ECSOption.from_text("ECS 2001:4b98::1/64/128")
+ self.assertEqual(ecs8, dns.edns.ECSOption("2001:4b98::1", 64, 128))
def testECSOption_from_text_invalid(self):
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('some random text 1.2.3.4/24/0 24')
+ dns.edns.ECSOption.from_text("some random text 1.2.3.4/24/0 24")
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('1.2.3.4/twentyfour')
+ dns.edns.ECSOption.from_text("1.2.3.4/twentyfour")
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('BOGUS 1.2.3.4/5/6/7')
+ dns.edns.ECSOption.from_text("BOGUS 1.2.3.4/5/6/7")
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('1.2.3.4/5/6/7')
+ dns.edns.ECSOption.from_text("1.2.3.4/5/6/7")
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('1.2.3.4/24/O') # <-- that's not a zero
+ dns.edns.ECSOption.from_text("1.2.3.4/24/O") # <-- that's not a zero
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('')
+ dns.edns.ECSOption.from_text("")
with self.assertRaises(ValueError):
- dns.edns.ECSOption.from_text('1.2.3.4/2001:4b98::1/24')
+ dns.edns.ECSOption.from_text("1.2.3.4/2001:4b98::1/24")
def testECSOption_from_wire_invalid(self):
with self.assertRaises(ValueError):
- opt = dns.edns.option_from_wire(dns.edns.ECS,
- b'\x00\xff\x18\x00\x01\x02\x03',
- 0, 7)
+ opt = dns.edns.option_from_wire(
+ dns.edns.ECS, b"\x00\xff\x18\x00\x01\x02\x03", 0, 7
+ )
+
def testEDEOption(self):
opt = dns.edns.EDEOption(3)
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x03')
- self.assertEqual(str(opt), 'EDE 3')
+ self.assertEqual(data, b"\x00\x03")
+ self.assertEqual(str(opt), "EDE 3")
# with text
- opt = dns.edns.EDEOption(16, 'test')
+ opt = dns.edns.EDEOption(16, "test")
io = BytesIO()
opt.to_wire(io)
data = io.getvalue()
- self.assertEqual(data, b'\x00\x10test')
+ self.assertEqual(data, b"\x00\x10test")
def testEDEOption_invalid(self):
with self.assertRaises(ValueError):
opt = dns.edns.EDEOption(0, 0)
def testEDEOption_from_wire(self):
- data = b'\x00\01'
+ data = b"\x00\01"
self.assertEqual(
- dns.edns.option_from_wire(dns.edns.EDE, data, 0, 2),
- dns.edns.EDEOption(1))
- data = b'\x00\01test'
+ dns.edns.option_from_wire(dns.edns.EDE, data, 0, 2), dns.edns.EDEOption(1)
+ )
+ data = b"\x00\01test"
self.assertEqual(
dns.edns.option_from_wire(dns.edns.EDE, data, 0, 6),
- dns.edns.EDEOption(1, 'test'))
+ dns.edns.EDEOption(1, "test"),
+ )
# utf-8 text MAY be null-terminated
- data = b'\x00\01test\x00'
+ data = b"\x00\01test\x00"
self.assertEqual(
dns.edns.option_from_wire(dns.edns.EDE, data, 0, 7),
- dns.edns.EDEOption(1, 'test'))
+ dns.edns.EDEOption(1, "test"),
+ )
def test_basic_relations(self):
- o1 = dns.edns.ECSOption.from_text('1.2.3.0/24/0')
- o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/0')
+ o1 = dns.edns.ECSOption.from_text("1.2.3.0/24/0")
+ o2 = dns.edns.ECSOption.from_text("1.2.4.0/24/0")
self.assertTrue(o1 == o1)
self.assertTrue(o1 != o2)
self.assertTrue(o1 < o2)
self.assertTrue(o1 <= o2)
self.assertTrue(o2 > o1)
self.assertTrue(o2 >= o1)
- o1 = dns.edns.ECSOption.from_text('1.2.4.0/23/0')
- o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/0')
+ o1 = dns.edns.ECSOption.from_text("1.2.4.0/23/0")
+ o2 = dns.edns.ECSOption.from_text("1.2.4.0/24/0")
self.assertTrue(o1 < o2)
- o1 = dns.edns.ECSOption.from_text('1.2.4.0/24/0')
- o2 = dns.edns.ECSOption.from_text('1.2.4.0/24/1')
+ o1 = dns.edns.ECSOption.from_text("1.2.4.0/24/0")
+ o2 = dns.edns.ECSOption.from_text("1.2.4.0/24/1")
self.assertTrue(o1 < o2)
def test_incompatible_relations(self):
- o1 = dns.edns.GenericOption(3, b'data')
- o2 = dns.edns.ECSOption.from_text('1.2.3.5/24/0')
+ o1 = dns.edns.GenericOption(3, b"data")
+ o2 = dns.edns.ECSOption.from_text("1.2.3.5/24/0")
for oper in [operator.lt, operator.le, operator.ge, operator.gt]:
self.assertRaises(TypeError, lambda: oper(o1, o2))
self.assertFalse(o1 == o2)
self.value = value
def to_wire(self, file=None):
- data = struct.pack('!I', self.value)
+ data = struct.pack("!I", self.value)
if file:
file.write(data)
else:
@classmethod
def from_wire_parser(cls, otype, parser):
- (value,) = parser.get_struct('!I')
+ (value,) = parser.get_struct("!I")
return cls(value)
try:
dns.edns.register_type(U32Option, U32OptionType)
- generic = dns.edns.GenericOption(U32OptionType, b'\x00\x00\x00\x01')
+ generic = dns.edns.GenericOption(U32OptionType, b"\x00\x00\x00\x01")
wire1 = generic.to_wire()
- u32 = dns.edns.option_from_wire_parser(U32OptionType,
- dns.wire.Parser(wire1))
+ u32 = dns.edns.option_from_wire_parser(
+ U32OptionType, dns.wire.Parser(wire1)
+ )
self.assertEqual(u32.value, 1)
wire2 = u32.to_wire()
self.assertEqual(wire1, wire2)
# these tests are mostly for minimal coverage testing
+
class EntropyTestCase(unittest.TestCase):
def test_pool(self):
- pool = dns.entropy.EntropyPool(b'seed-value')
+ pool = dns.entropy.EntropyPool(b"seed-value")
self.assertEqual(pool.random_8(), 94)
self.assertEqual(pool.random_16(), 61532)
self.assertEqual(pool.random_32(), 4226376065)
self.assertEqual(pool.random_between(10, 50), 29)
# stir in some not-really-entropy to exercise the stir API
- pool.stir(b'not-really-entropy')
+ pool.stir(b"not-really-entropy")
def test_pool_random(self):
pool = dns.entropy.EntropyPool()
def test_pool_random_between(self):
pool = dns.entropy.EntropyPool()
+
def bad():
pool.random_between(0, 4294967296)
+
self.assertRaises(ValueError, bad)
v = pool.random_between(50, 50 + 100000)
self.assertTrue(v >= 50 and v <= 50 + 100000)
class EntropyForcePoolTestCase(unittest.TestCase):
-
def setUp(self):
self.saved_system_random = dns.entropy.system_random
dns.entropy.system_random = None
class FormatedError(DNSException):
fmt = "Custom format: {parameter}"
- supp_kwargs = {'parameter'}
+ supp_kwargs = {"parameter"}
class ExceptionTestCase(unittest.TestCase):
-
def test_custom_message(self):
msg = "this is a custom message"
try:
def test_formatted_error(self):
"""Exceptions with explicit format has to respect it."""
- params = {'parameter': 'value'}
+ params = {"parameter": "value"}
try:
raise FormatedError(**params)
except FormatedError as ex:
with self.assertRaises(AssertionError):
raise FormatedError(unsupported=2)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
import dns.rcode
import dns.opcode
-class FlagsTestCase(unittest.TestCase):
+class FlagsTestCase(unittest.TestCase):
def test_rcode1(self):
- self.assertEqual(dns.rcode.from_text('FORMERR'), dns.rcode.FORMERR)
+ self.assertEqual(dns.rcode.from_text("FORMERR"), dns.rcode.FORMERR)
def test_rcode2(self):
self.assertEqual(dns.rcode.to_text(dns.rcode.FORMERR), "FORMERR")
self.assertEqual(dns.rcode.to_flags(dns.rcode.FORMERR), (1, 0))
def test_rcode4(self):
- self.assertEqual(dns.rcode.to_flags(dns.rcode.BADVERS),
- (0, 0x01000000))
+ self.assertEqual(dns.rcode.to_flags(dns.rcode.BADVERS), (0, 0x01000000))
def test_rcode6(self):
- self.assertEqual(dns.rcode.from_flags(0, 0x01000000),
- dns.rcode.BADVERS)
+ self.assertEqual(dns.rcode.from_flags(0, 0x01000000), dns.rcode.BADVERS)
def test_rcode7(self):
self.assertEqual(dns.rcode.from_flags(5, 0), dns.rcode.REFUSED)
def test_rcode8(self):
def bad():
dns.rcode.to_flags(4096)
+
self.assertRaises(ValueError, bad)
def test_flags1(self):
- self.assertEqual(dns.flags.from_text("RA RD AA QR"),
- dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA)
+ self.assertEqual(
+ dns.flags.from_text("RA RD AA QR"),
+ dns.flags.QR | dns.flags.AA | dns.flags.RD | dns.flags.RA,
+ )
def test_flags2(self):
- flags = dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA
+ flags = dns.flags.QR | dns.flags.AA | dns.flags.RD | dns.flags.RA
self.assertEqual(dns.flags.to_text(flags), "QR AA RD RA")
def test_rcode_badvers(self):
rcode = dns.rcode.BADVERS
self.assertEqual(rcode.value, 16)
- self.assertEqual(rcode.name, 'BADVERS')
- self.assertEqual(dns.rcode.to_text(rcode), 'BADVERS')
+ self.assertEqual(rcode.name, "BADVERS")
+ self.assertEqual(dns.rcode.to_text(rcode), "BADVERS")
def test_rcode_badsig(self):
rcode = dns.rcode.BADSIG
self.assertEqual(rcode.value, 16)
# Yes, we mean BADVERS on the next line. BADSIG and BADVERS have
# the same code.
- self.assertEqual(rcode.name, 'BADVERS')
- self.assertEqual(dns.rcode.to_text(rcode), 'BADVERS')
+ self.assertEqual(rcode.name, "BADVERS")
+ self.assertEqual(dns.rcode.to_text(rcode), "BADVERS")
# In TSIG text mode, it should be BADSIG
- self.assertEqual(dns.rcode.to_text(rcode, True), 'BADSIG')
+ self.assertEqual(dns.rcode.to_text(rcode, True), "BADSIG")
def test_unknown_rcode(self):
with self.assertRaises(dns.rcode.UnknownRcode):
- dns.rcode.Rcode.make('BOGUS')
+ dns.rcode.Rcode.make("BOGUS")
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import sys
-sys.path.insert(0, '../') # Force the local project to be *the* dns
+
+sys.path.insert(0, "../") # Force the local project to be *the* dns
import unittest
@ 3600 IN NS ns2
"""
+
def _rdata_sort(a):
return (a[0], a[2].rdclass, a[2].to_text())
class GenerateTestCase(unittest.TestCase):
+ def testFromText(self): # type: () -> None
+ def bad(): # type: () -> None
+ dns.zone.from_text(example_text, "example.", relativize=True)
- def testFromText(self): # type: () -> None
- def bad(): # type: () -> None
- dns.zone.from_text(example_text, 'example.', relativize=True)
self.assertRaises(dns.zone.NoSOA, bad)
- def testFromText1(self): # type: () -> None
- def bad(): # type: () -> None
- dns.zone.from_text(example_text1, 'example.', relativize=True)
+ def testFromText1(self): # type: () -> None
+ def bad(): # type: () -> None
+ dns.zone.from_text(example_text1, "example.", relativize=True)
+
self.assertRaises(dns.zone.NoSOA, bad)
- def testIterateAllRdatas2(self): # type: () -> None
- z = dns.zone.from_text(example_text2, 'example.', relativize=True)
+ def testIterateAllRdatas2(self): # type: () -> None
+ z = dns.zone.from_text(example_text2, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')),
- (dns.name.from_text('foo3', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.3')),
- (dns.name.from_text('foo4', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.4')),
- (dns.name.from_text('foo5', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.5'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ (
+ dns.name.from_text("foo3", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.3"),
+ ),
+ (
+ dns.name.from_text("foo4", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.4"),
+ ),
+ (
+ dns.name.from_text("foo5", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.5"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testIterateAllRdatas3(self): # type: () -> None
- z = dns.zone.from_text(example_text3, 'example.', relativize=True)
+ def testIterateAllRdatas3(self): # type: () -> None
+ z = dns.zone.from_text(example_text3, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')),
- (dns.name.from_text('foo4', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.4')),
- (dns.name.from_text('foo6', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.6')),
- (dns.name.from_text('foo8', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.8'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ (
+ dns.name.from_text("foo4", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.4"),
+ ),
+ (
+ dns.name.from_text("foo6", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.6"),
+ ),
+ (
+ dns.name.from_text("foo8", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.8"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate1(self): # type: () -> None
- z = dns.zone.from_text(example_text4, 'example.', relativize=True)
+
+ def testGenerate1(self): # type: () -> None
+ z = dns.zone.from_text(example_text4, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 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),
- 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db02.services.mozilla.com', None),
- 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db03.services.mozilla.com', None),
- 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 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),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db02.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db03.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate2(self): # type: () -> None
- z = dns.zone.from_text(example_text5, 'example.', relativize=True)
+ def testGenerate2(self): # type: () -> None
+ z = dns.zone.from_text(example_text5, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 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), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db22.services.mozilla.com', None), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db23.services.mozilla.com', None), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 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),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db22.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db23.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate3(self): # type: () -> None
- z = dns.zone.from_text(example_text6, 'example.', relativize=True)
+ def testGenerate3(self): # type: () -> None
+ z = dns.zone.from_text(example_text6, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 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), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db22.services.mozilla.com', None), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.')),
-
- (dns.name.from_text('wp-db23.services.mozilla.com', None), 0,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- 'SERVER.FOOBAR.'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 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),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db22.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ (
+ dns.name.from_text("wp-db23.services.mozilla.com", None),
+ 0,
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR."
+ ),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate4(self): # type: () -> None
- z = dns.zone.from_text(example_text7, 'example.', relativize=True)
+ def testGenerate4(self): # type: () -> None
+ z = dns.zone.from_text(example_text7, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')),
-
- (dns.name.from_text('sync1.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
-
- (dns.name.from_text('sync2.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
-
- (dns.name.from_text('sync3.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ (
+ dns.name.from_text("sync1.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("sync2.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("sync3.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate6(self): # type: () -> None
- z = dns.zone.from_text(example_text9, 'example.', relativize=True)
+ def testGenerate6(self): # type: () -> None
+ z = dns.zone.from_text(example_text9, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')),
-
- (dns.name.from_text('wp-db01', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
- (dns.name.from_text('wp-db02', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
-
- (dns.name.from_text('sync1.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
-
- (dns.name.from_text('sync2.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0')),
-
- (dns.name.from_text('sync3.db', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.10.16.0'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ (
+ dns.name.from_text("wp-db01", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("wp-db02", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("sync1.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("sync2.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ (
+ dns.name.from_text("sync3.db", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate7(self): # type: () -> None
- z = dns.zone.from_text(example_text10, 'example.', relativize=True)
+ def testGenerate7(self): # type: () -> None
+ z = dns.zone.from_text(example_text10, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')),
-
- (dns.name.from_text('27.2', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
- 'zlb1.oob')),
-
- (dns.name.from_text('28.2', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
- 'zlb2.oob'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ (
+ dns.name.from_text("27.2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, "zlb1.oob"),
+ ),
+ (
+ dns.name.from_text("28.2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, "zlb2.oob"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
- def testGenerate8(self): # type: () -> None
- z = dns.zone.from_text(example_text11, 'example.', relativize=True)
+ def testGenerate8(self): # type: () -> None
+ z = dns.zone.from_text(example_text11, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
- 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),
+ exl = [
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
+ 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),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
-
- (dns.name.from_text('prefix-027', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.27')),
-
- (dns.name.from_text('prefix-028', None), 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.28')),
-
- (dns.name.from_text('ns1', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
- 3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("prefix-027", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.27"),
+ ),
+ (
+ dns.name.from_text("prefix-028", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.28"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
+ 3600,
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
def testNoOrigin(self):
def bad():
- dns.zone.from_text('$GENERATE 1-10 fooo$ CNAME $.0')
+ dns.zone.from_text("$GENERATE 1-10 fooo$ CNAME $.0")
+
self.assertRaises(dns.zone.UnknownOrigin, bad)
def testBadRdata(self):
def bad():
- dns.zone.from_text('$GENERATE 1-10 fooo$ CNAME 10 $.0', 'example')
+ dns.zone.from_text("$GENERATE 1-10 fooo$ CNAME 10 $.0", "example")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testUsesLastTTL(self):
- z = dns.zone.from_text(last_ttl_input, 'example')
- rrs = z.find_rrset('foo9', 'CNAME')
+ z = dns.zone.from_text(last_ttl_input, "example")
+ rrs = z.find_rrset("foo9", "CNAME")
self.assertEqual(rrs.ttl, 300)
def testClassMismatch(self):
def bad():
- dns.zone.from_text('$GENERATE 1-10 fooo$ CH CNAME $.0', 'example')
+ dns.zone.from_text("$GENERATE 1-10 fooo$ CH CNAME $.0", "example")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testUnknownRdatatype(self):
def bad():
- dns.zone.from_text('$GENERATE 1-10 fooo$ BOGUSTYPE $.0', 'example')
+ dns.zone.from_text("$GENERATE 1-10 fooo$ BOGUSTYPE $.0", "example")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testBadAndDangling(self):
def bad1():
- dns.zone.from_text('$GENERATE bogus fooo$ CNAME $.0',
- 'example.')
+ dns.zone.from_text("$GENERATE bogus fooo$ CNAME $.0", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad1)
+
def bad2():
- dns.zone.from_text('$GENERATE 1-10',
- 'example.')
+ dns.zone.from_text("$GENERATE 1-10", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad2)
+
def bad3():
- dns.zone.from_text('$GENERATE 1-10 foo$',
- 'example.')
+ dns.zone.from_text("$GENERATE 1-10 foo$", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad3)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import sys
-sys.path.insert(0, '../')
+
+sys.path.insert(0, "../")
import unittest
class GRangeTestCase(unittest.TestCase):
-
def testFromText1(self):
- start, stop, step = dns.grange.from_text('1-1')
+ start, stop, step = dns.grange.from_text("1-1")
self.assertEqual(start, 1)
self.assertEqual(stop, 1)
self.assertEqual(step, 1)
def testFromText2(self):
- start, stop, step = dns.grange.from_text('1-4')
+ start, stop, step = dns.grange.from_text("1-4")
self.assertEqual(start, 1)
self.assertEqual(stop, 4)
self.assertEqual(step, 1)
def testFromText3(self):
- start, stop, step = dns.grange.from_text('4-255')
+ start, stop, step = dns.grange.from_text("4-255")
self.assertEqual(start, 4)
self.assertEqual(stop, 255)
self.assertEqual(step, 1)
def testFromText4(self):
- start, stop, step = dns.grange.from_text('1-1/1')
+ start, stop, step = dns.grange.from_text("1-1/1")
self.assertEqual(start, 1)
self.assertEqual(stop, 1)
self.assertEqual(step, 1)
def testFromText5(self):
- start, stop, step = dns.grange.from_text('1-4/2')
+ start, stop, step = dns.grange.from_text("1-4/2")
self.assertEqual(start, 1)
self.assertEqual(stop, 4)
self.assertEqual(step, 2)
def testFromText6(self):
- start, stop, step = dns.grange.from_text('4-255/77')
+ start, stop, step = dns.grange.from_text("4-255/77")
self.assertEqual(start, 4)
self.assertEqual(stop, 255)
self.assertEqual(step, 77)
start = 2
stop = 1
step = 1
- dns.grange.from_text('%d-%d/%d' % (start, stop, step))
+ dns.grange.from_text("%d-%d/%d" % (start, stop, step))
self.assertTrue(False)
def testFailFromText2(self):
with self.assertRaises(dns.exception.SyntaxError):
- start = '-1'
+ start = "-1"
stop = 3
step = 1
- dns.grange.from_text('%s-%d/%d' % (start, stop, step))
+ dns.grange.from_text("%s-%d/%d" % (start, stop, step))
def testFailFromText3(self):
with self.assertRaises(dns.exception.SyntaxError):
start = 1
stop = 4
- step = '-2'
- dns.grange.from_text('%d-%d/%s' % (start, stop, step))
+ step = "-2"
+ dns.grange.from_text("%d-%d/%s" % (start, stop, step))
def testFailFromText4(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.grange.from_text('1')
+ dns.grange.from_text("1")
+
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
class ImmutableTestCase(unittest.TestCase):
-
def test_immutable_dict_hash(self):
- d1 = dns.immutable.Dict({'a': 1, 'b': 2})
- d2 = dns.immutable.Dict({'b': 2, 'a': 1})
- d3 = {'b': 2, 'a': 1}
+ d1 = dns.immutable.Dict({"a": 1, "b": 2})
+ d2 = dns.immutable.Dict({"b": 2, "a": 1})
+ d3 = {"b": 2, "a": 1}
self.assertEqual(d1, d2)
self.assertEqual(d2, d3)
self.assertEqual(hash(d1), hash(d2))
def test_immutable_dict_hash_cache(self):
- d = dns.immutable.Dict({'a': 1, 'b': 2})
+ d = dns.immutable.Dict({"a": 1, "b": 2})
self.assertEqual(d._hash, None)
h1 = hash(d)
self.assertEqual(d._hash, h1)
def test_constify(self):
items = (
- (bytearray([1, 2, 3]), b'\x01\x02\x03'),
+ (bytearray([1, 2, 3]), b"\x01\x02\x03"),
((1, 2, 3), (1, 2, 3)),
((1, [2], 3), (1, (2,), 3)),
([1, 2, 3], (1, 2, 3)),
- ([1, {'a': [1, 2]}],
- (1, dns.immutable.Dict({'a': (1, 2)}))),
- ('hi', 'hi'),
- (b'hi', b'hi'),
+ ([1, {"a": [1, 2]}], (1, dns.immutable.Dict({"a": (1, 2)}))),
+ ("hi", "hi"),
+ (b"hi", b"hi"),
)
for input, expected in items:
self.assertEqual(dns.immutable.constify(input), expected)
- self.assertIsInstance(dns.immutable.constify({'a': 1}),
- dns.immutable.Dict)
+ self.assertIsInstance(dns.immutable.constify({"a": 1}), dns.immutable.Dict)
class DecoratorTestCase(unittest.TestCase):
def __init__(self, a, b):
super().__init__(a, akw=20)
self.b = b
+
B = self.immutable_module.immutable(B)
# note C is immutable by inheritance
def __init__(self, a, b, c):
super().__init__(a, b)
self.c = c
+
C = self.immutable_module.immutable(C)
class SA:
- __slots__ = ('a', 'akw')
+ __slots__ = ("a", "akw")
+
def __init__(self, a, akw=10):
self.a = a
self.akw = akw
class SB(A):
- __slots__ = ('b')
+ __slots__ = "b"
+
def __init__(self, a, b):
super().__init__(a, akw=20)
self.b = b
+
SB = self.immutable_module.immutable(SB)
# note SC is immutable by inheritance and has no slots of its own
def __init__(self, a, b, c):
super().__init__(a, b)
self.c = c
+
SC = self.immutable_module.immutable(SC)
return ((A, B, C), (SA, SB, SC))
self.a = a
self.b = a
del self.b
+
A = self.immutable_module.immutable(A)
a = A(10)
self.assertEqual(a.a, 10)
- self.assertFalse(hasattr(a, 'b'))
+ self.assertFalse(hasattr(a, "b"))
def test_no_collateral_damage(self):
class A:
def __init__(self, a):
self.a = a
+
A = self.immutable_module.immutable(A)
class B:
self.b = a.a + b
# rudely attempt to mutate innocent immutable bystander 'a'
a.a = 1000
+
B = self.immutable_module.immutable(B)
a = A(10)
;AUTHORITY
;ADDITIONAL"""
-goodhex = b'04d201000001000000000001047777777709646e73707974686f6e' \
- b'036f726700000100010000291000000080000000'
+goodhex = (
+ b"04d201000001000000000001047777777709646e73707974686f6e"
+ b"036f726700000100010000291000000080000000"
+)
goodwire = binascii.unhexlify(goodhex)
woof.play-bow.org. 3600 IN A 204.152.186.150
"""
-goodhex2 = '04d2 8500 0001 0001 0003 0001' \
- '09646e73707974686f6e036f726700 0006 0001' \
- 'c00c 0006 0001 00000e10 0028 ' \
- '04776f6f66c00c 0a686f73746d6173746572c00c' \
- '7764289c 00000e10 00000708 00093a80 00000e10' \
- 'c00c 0002 0001 00000e10 0014' \
- '036e7331057374616666076e6f6d696e756dc016' \
- 'c00c 0002 0001 00000e10 0006 036e7332c063' \
- 'c00c 0002 0001 00000e10 0010 04776f6f6608706c61792d626f77c016' \
- 'c091 0001 0001 00000e10 0004 cc98ba96'
+goodhex2 = (
+ "04d2 8500 0001 0001 0003 0001"
+ "09646e73707974686f6e036f726700 0006 0001"
+ "c00c 0006 0001 00000e10 0028 "
+ "04776f6f66c00c 0a686f73746d6173746572c00c"
+ "7764289c 00000e10 00000708 00093a80 00000e10"
+ "c00c 0002 0001 00000e10 0014"
+ "036e7331057374616666076e6f6d696e756dc016"
+ "c00c 0002 0001 00000e10 0006 036e7332c063"
+ "c00c 0002 0001 00000e10 0010 04776f6f6608706c61792d626f77c016"
+ "c091 0001 0001 00000e10 0004 cc98ba96"
+)
-goodwire2 = binascii.unhexlify(goodhex2.replace(' ', '').encode())
+goodwire2 = binascii.unhexlify(goodhex2.replace(" ", "").encode())
query_text_2 = """id 1234
opcode QUERY
;AUTHORITY
;ADDITIONAL"""
-goodhex3 = b'04d2010f0001000000000001047777777709646e73707974686f6e' \
- b'036f726700000100010000291000ff0080000000'
+goodhex3 = (
+ b"04d2010f0001000000000001047777777709646e73707974686f6e"
+ b"036f726700000100010000291000ff0080000000"
+)
goodwire3 = binascii.unhexlify(goodhex3)
Königsgäßchen. 3600 IN NS Königsgäßchen.
"""
-class MessageTestCase(unittest.TestCase):
+class MessageTestCase(unittest.TestCase):
def test_class(self):
m = dns.message.from_text(query_text)
self.assertTrue(isinstance(m, dns.message.QueryMessage))
self.assertEqual(str(m), query_text_2)
def test_EDNS_options_wire(self):
- m = dns.message.make_query('foo', 'A')
- opt = dns.edns.GenericOption(3, b'data')
+ m = dns.message.make_query("foo", "A")
+ opt = dns.edns.GenericOption(3, b"data")
m.use_edns(options=[opt])
m2 = dns.message.from_wire(m.to_wire())
self.assertEqual(m2.edns, 0)
def bad():
q = dns.message.from_text(query_text)
for i in range(0, 25):
- rrset = dns.rrset.from_text('foo%d.' % i, 3600,
- dns.rdataclass.IN,
- dns.rdatatype.A,
- '10.0.0.%d' % i)
+ rrset = dns.rrset.from_text(
+ "foo%d." % i,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ "10.0.0.%d" % i,
+ )
q.additional.append(rrset)
q.to_wire(max_size=512)
+
self.assertRaises(dns.exception.TooBig, bad)
def test_answer1(self):
def test_TrailingJunk(self):
def bad():
- badwire = goodwire + b'\x00'
+ badwire = goodwire + b"\x00"
dns.message.from_wire(badwire)
+
self.assertRaises(dns.message.TrailingJunk, bad)
def test_ShortHeader(self):
def bad():
- badwire = b'\x00' * 11
+ badwire = b"\x00" * 11
dns.message.from_wire(badwire)
+
self.assertRaises(dns.message.ShortHeader, bad)
def test_RespondingToResponse(self):
def bad():
- q = dns.message.make_query('foo', 'A')
+ q = dns.message.make_query("foo", "A")
r1 = dns.message.make_response(q)
dns.message.make_response(r1)
+
self.assertRaises(dns.exception.FormError, bad)
def test_RespondingToEDNSRequestAndSettingRA(self):
- q = dns.message.make_query('foo', 'A', use_edns=0)
+ q = dns.message.make_query("foo", "A", use_edns=0)
r = dns.message.make_response(q, True)
self.assertTrue(r.flags & dns.flags.RA != 0)
self.assertEqual(r.edns, 0)
def test_ExtendedRcodeSetting(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
m.set_rcode(4095)
self.assertEqual(m.rcode(), 4095)
self.assertEqual(m.edns, 0)
self.assertEqual(m.rcode(), 2)
def test_EDNSVersionCoherence(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
m.use_edns(1)
self.assertEqual((m.ednsflags >> 16) & 0xFF, 1)
def test_SettingNoEDNSOptionsImpliesNoEDNS(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
self.assertEqual(m.edns, -1)
def test_SettingEDNSFlagsImpliesEDNS(self):
- m = dns.message.make_query('foo', 'A', ednsflags=dns.flags.DO)
+ m = dns.message.make_query("foo", "A", ednsflags=dns.flags.DO)
self.assertEqual(m.edns, 0)
def test_SettingEDNSPayloadImpliesEDNS(self):
- m = dns.message.make_query('foo', 'A', payload=4096)
+ m = dns.message.make_query("foo", "A", payload=4096)
self.assertEqual(m.edns, 0)
def test_SettingEDNSRequestPayloadImpliesEDNS(self):
- m = dns.message.make_query('foo', 'A', request_payload=4096)
+ m = dns.message.make_query("foo", "A", request_payload=4096)
self.assertEqual(m.edns, 0)
def test_SettingOptionsImpliesEDNS(self):
- m = dns.message.make_query('foo', 'A', options=[])
+ m = dns.message.make_query("foo", "A", options=[])
self.assertEqual(m.edns, 0)
def test_FindRRset(self):
a = dns.message.from_text(answer_text)
- n = dns.name.from_text('dnspython.org.')
+ n = dns.name.from_text("dnspython.org.")
rrs1 = a.find_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA)
- rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN,
- dns.rdatatype.SOA)
+ rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, dns.rdatatype.SOA)
self.assertEqual(rrs1, rrs2)
def test_FindRRsetUnindexed(self):
a = dns.message.from_text(answer_text)
a.index = None
- n = dns.name.from_text('dnspython.org.')
+ n = dns.name.from_text("dnspython.org.")
rrs1 = a.find_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA)
- rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN,
- dns.rdatatype.SOA)
+ rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, dns.rdatatype.SOA)
self.assertEqual(rrs1, rrs2)
def test_GetRRset(self):
a = dns.message.from_text(answer_text)
a.index = None
- n = dns.name.from_text('dnspython.org.')
+ n = dns.name.from_text("dnspython.org.")
rrs1 = a.get_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA)
- rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN,
- dns.rdatatype.SOA)
+ rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, dns.rdatatype.SOA)
self.assertEqual(rrs1, rrs2)
def test_GetNonexistentRRset(self):
a = dns.message.from_text(answer_text)
a.index = None
- n = dns.name.from_text('dnspython.org.')
+ n = dns.name.from_text("dnspython.org.")
rrs1 = a.get_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.TXT)
- rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN,
- dns.rdatatype.TXT)
+ rrs2 = a.get_rrset(dns.message.ANSWER, n, dns.rdataclass.IN, dns.rdatatype.TXT)
self.assertTrue(rrs1 is None)
self.assertEqual(rrs1, rrs2)
a.flags |= dns.flags.TC
wire = a.to_wire(want_shuffle=False)
dns.message.from_wire(wire, raise_on_truncation=True)
+
self.assertRaises(dns.message.Truncated, bad)
def test_MessyTruncated(self):
a.flags |= dns.flags.TC
wire = a.to_wire(want_shuffle=False)
dns.message.from_wire(wire[:-3], raise_on_truncation=True)
+
self.assertRaises(dns.message.Truncated, bad)
def test_IDNA_2003(self):
a = dns.message.from_text(idna_text, idna_codec=dns.name.IDNA_2003)
- rrs = dns.rrset.from_text_list('xn--knigsgsschen-lcb0w.', 30,
- 'in', 'ns',
- ['xn--knigsgsschen-lcb0w.'],
- idna_codec=dns.name.IDNA_2003)
+ rrs = dns.rrset.from_text_list(
+ "xn--knigsgsschen-lcb0w.",
+ 30,
+ "in",
+ "ns",
+ ["xn--knigsgsschen-lcb0w."],
+ idna_codec=dns.name.IDNA_2003,
+ )
self.assertEqual(a.answer[0], rrs)
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def test_IDNA_2008(self):
a = dns.message.from_text(idna_text, idna_codec=dns.name.IDNA_2008)
- rrs = dns.rrset.from_text_list('xn--knigsgchen-b4a3dun.', 30,
- 'in', 'ns',
- ['xn--knigsgchen-b4a3dun.'],
- idna_codec=dns.name.IDNA_2008)
+ rrs = dns.rrset.from_text_list(
+ "xn--knigsgchen-b4a3dun.",
+ 30,
+ "in",
+ "ns",
+ ["xn--knigsgchen-b4a3dun."],
+ idna_codec=dns.name.IDNA_2008,
+ )
self.assertEqual(a.answer[0], rrs)
def test_bad_section_number(self):
- m = dns.message.make_query('foo', 'A')
- self.assertRaises(ValueError,
- lambda: m.section_number(123))
+ m = dns.message.make_query("foo", "A")
+ self.assertRaises(ValueError, lambda: m.section_number(123))
def test_section_from_number(self):
- m = dns.message.make_query('foo', 'A')
- self.assertEqual(m.section_from_number(dns.message.QUESTION),
- m.question)
- self.assertEqual(m.section_from_number(dns.message.ANSWER),
- m.answer)
- self.assertEqual(m.section_from_number(dns.message.AUTHORITY),
- m.authority)
- self.assertEqual(m.section_from_number(dns.message.ADDITIONAL),
- m.additional)
- self.assertRaises(ValueError,
- lambda: m.section_from_number(999))
+ m = dns.message.make_query("foo", "A")
+ self.assertEqual(m.section_from_number(dns.message.QUESTION), m.question)
+ self.assertEqual(m.section_from_number(dns.message.ANSWER), m.answer)
+ self.assertEqual(m.section_from_number(dns.message.AUTHORITY), m.authority)
+ self.assertEqual(m.section_from_number(dns.message.ADDITIONAL), m.additional)
+ self.assertRaises(ValueError, lambda: m.section_from_number(999))
def test_wanting_EDNS_true_is_EDNS0(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
self.assertEqual(m.edns, -1)
m.use_edns(True)
self.assertEqual(m.edns, 0)
def test_wanting_DNSSEC_turns_on_EDNS(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
self.assertEqual(m.edns, -1)
m.want_dnssec()
self.assertEqual(m.edns, 0)
self.assertTrue(m.ednsflags & dns.flags.DO)
def test_EDNS_default_payload_is_1232(self):
- m = dns.message.make_query('foo', 'A')
+ m = dns.message.make_query("foo", "A")
m.use_edns()
self.assertEqual(m.payload, dns.message.DEFAULT_EDNS_PAYLOAD)
def test_from_file(self):
- m = dns.message.from_file(here('query'))
+ m = dns.message.from_file(here("query"))
expected = dns.message.from_text(query_text)
self.assertEqual(m, expected)
def test_explicit_header_comment(self):
- m = dns.message.from_text(';HEADER\n' + query_text)
+ m = dns.message.from_text(";HEADER\n" + query_text)
expected = dns.message.from_text(query_text)
self.assertEqual(m, expected)
def test_repr(self):
q = dns.message.from_text(query_text)
- self.assertEqual(repr(q), '<DNS message, ID 1234>')
+ self.assertEqual(repr(q), "<DNS message, ID 1234>")
def test_non_question_setters(self):
- rrset = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1')
+ rrset = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1")
q = dns.message.QueryMessage(id=1)
q.answer = [rrset]
self.assertEqual(q.sections[1], [rrset])
self.assertEqual(q.sections[3], [rrset])
def test_is_a_response_empty_question(self):
- q = dns.message.make_query('www.dnspython.org.', 'a')
+ q = dns.message.make_query("www.dnspython.org.", "a")
r = dns.message.make_response(q)
r.question = []
r.set_rcode(dns.rcode.FORMERR)
self.assertFalse(q.is_response(r))
r = dns.update.UpdateMessage(id=1)
self.assertFalse(q.is_response(r))
- q1 = dns.message.make_query('www.dnspython.org.', 'a')
- q2 = dns.message.make_query('www.google.com.', 'a')
+ q1 = dns.message.make_query("www.dnspython.org.", "a")
+ q2 = dns.message.make_query("www.google.com.", "a")
# Give them the same id, as we want to test if responses for
# differing questions are rejected.
q1.id = 1
# something in the response's question section that is not in
# the question's. We have to do multiple questions to test
# this :)
- r = dns.message.make_query('www.dnspython.org.', 'a')
+ r = dns.message.make_query("www.dnspython.org.", "a")
r.flags |= dns.flags.QR
r.id = 1
- r.find_rrset(r.question, dns.name.from_text('example'),
- dns.rdataclass.IN, dns.rdatatype.A, create=True,
- force_unique=True)
+ r.find_rrset(
+ r.question,
+ dns.name.from_text("example"),
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ create=True,
+ force_unique=True,
+ )
self.assertFalse(q1.is_response(r))
def test_more_not_equal_cases(self):
- q1 = dns.message.make_query('www.dnspython.org.', 'a')
- q2 = dns.message.make_query('www.dnspython.org.', 'a')
+ q1 = dns.message.make_query("www.dnspython.org.", "a")
+ q2 = dns.message.make_query("www.dnspython.org.", "a")
# ensure ids are same
q1.id = 1
q2.id = 1
q2.flags |= dns.flags.QR
self.assertFalse(q1 == q2)
q2.flags = q1.flags
- q2.find_rrset(q2.question, dns.name.from_text('example'),
- dns.rdataclass.IN, dns.rdatatype.A, create=True,
- force_unique=True)
+ q2.find_rrset(
+ q2.question,
+ dns.name.from_text("example"),
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ create=True,
+ force_unique=True,
+ )
self.assertFalse(q1 == q2)
def test_edns_properties(self):
- q = dns.message.make_query('www.dnspython.org.', 'a')
+ q = dns.message.make_query("www.dnspython.org.", "a")
self.assertEqual(q.edns, -1)
self.assertEqual(q.payload, 0)
self.assertEqual(q.options, ())
- q = dns.message.make_query('www.dnspython.org.', 'a', use_edns=0,
- payload=4096)
+ q = dns.message.make_query("www.dnspython.org.", "a", use_edns=0, payload=4096)
self.assertEqual(q.edns, 0)
self.assertEqual(q.payload, 4096)
self.assertEqual(q.options, ())
def test_setting_id(self):
- q = dns.message.make_query('www.dnspython.org.', 'a', id=12345)
+ q = dns.message.make_query("www.dnspython.org.", "a", id=12345)
self.assertEqual(q.id, 12345)
def test_setting_flags(self):
- q = dns.message.make_query('www.dnspython.org.', 'a',
- flags=dns.flags.RD|dns.flags.CD)
- self.assertEqual(q.flags, dns.flags.RD|dns.flags.CD)
+ q = dns.message.make_query(
+ "www.dnspython.org.", "a", flags=dns.flags.RD | dns.flags.CD
+ )
+ self.assertEqual(q.flags, dns.flags.RD | dns.flags.CD)
self.assertEqual(q.flags, 0x0110)
def test_generic_message_class(self):
q1 = dns.message.Message(id=1)
q1.set_opcode(dns.opcode.NOTIFY)
q1.flags |= dns.flags.AA
- q1.find_rrset(q1.question, dns.name.from_text('example'),
- dns.rdataclass.IN, dns.rdatatype.SOA, create=True,
- force_unique=True)
+ q1.find_rrset(
+ q1.question,
+ dns.name.from_text("example"),
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ create=True,
+ force_unique=True,
+ )
w = q1.to_wire()
q2 = dns.message.from_wire(w)
self.assertTrue(isinstance(q2, dns.message.Message))
dns.message.from_wire(wire)
# Owner name not root name
q = dns.message.Message(id=1)
- rrs = dns.rrset.from_rdata('foo.', 0, opt)
+ rrs = dns.rrset.from_rdata("foo.", 0, opt)
q.additional.append(rrs)
wire = q.to_wire()
with self.assertRaises(dns.message.BadEDNS):
dns.message.from_wire(wire)
def test_bad_tsig(self):
- keyname = dns.name.from_text('key.')
+ keyname = dns.name.from_text("key.")
# Not in additional
q = dns.message.Message(id=1)
- tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.ANY, dns.rdatatype.TSIG,
- dns.tsig.HMAC_SHA256, 0, 300, b'1234',
- 0, 0, b'')
+ tsig = dns.rdtypes.ANY.TSIG.TSIG(
+ dns.rdataclass.ANY,
+ dns.rdatatype.TSIG,
+ dns.tsig.HMAC_SHA256,
+ 0,
+ 300,
+ b"1234",
+ 0,
+ 0,
+ b"",
+ )
rrs = dns.rrset.from_rdata(keyname, 0, tsig)
q.answer.append(rrs)
wire = q.to_wire()
with self.assertRaises(dns.message.BadTSIG):
dns.message.from_wire(wire)
# Class not ANY
- tsig = dns.rdtypes.ANY.TSIG.TSIG(dns.rdataclass.IN, dns.rdatatype.TSIG,
- dns.tsig.HMAC_SHA256, 0, 300, b'1234',
- 0, 0, b'')
+ tsig = dns.rdtypes.ANY.TSIG.TSIG(
+ dns.rdataclass.IN,
+ dns.rdatatype.TSIG,
+ dns.tsig.HMAC_SHA256,
+ 0,
+ 300,
+ b"1234",
+ 0,
+ 0,
+ b"",
+ )
rrs = dns.rrset.from_rdata(keyname, 0, tsig)
wire = q.to_wire()
with self.assertRaises(dns.message.BadTSIG):
dns.message.from_wire(wire)
def test_read_no_content_message(self):
- m = dns.message.from_text(';comment')
+ m = dns.message.from_text(";comment")
self.assertIsInstance(m, dns.message.QueryMessage)
def test_eflags_turns_on_edns(self):
- m = dns.message.from_text('eflags DO')
+ m = dns.message.from_text("eflags DO")
self.assertIsInstance(m, dns.message.QueryMessage)
self.assertEqual(m.edns, 0)
def test_payload_turns_on_edns(self):
- m = dns.message.from_text('payload 1200')
+ m = dns.message.from_text("payload 1200")
self.assertIsInstance(m, dns.message.QueryMessage)
self.assertEqual(m.payload, 1200)
def test_bogus_header(self):
with self.assertRaises(dns.message.UnknownHeaderField):
- dns.message.from_text('bogus foo')
+ dns.message.from_text("bogus foo")
def test_question_only(self):
m = dns.message.from_text(answer_text)
self.assertEqual(len(r.additional), 0)
def test_bad_resolve_chaining(self):
- r = dns.message.make_query('www.dnspython.org.', 'a')
+ r = dns.message.make_query("www.dnspython.org.", "a")
with self.assertRaises(dns.message.NotQueryResponse):
r.resolve_chaining()
r.flags |= dns.flags.QR
r.id = 1
- r.find_rrset(r.question, dns.name.from_text('example'),
- dns.rdataclass.IN, dns.rdatatype.A, create=True,
- force_unique=True)
+ r.find_rrset(
+ r.question,
+ dns.name.from_text("example"),
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ create=True,
+ force_unique=True,
+ )
with self.assertRaises(dns.exception.FormError):
r.resolve_chaining()
def test_resolve_chaining_no_infinite_loop(self):
- r = dns.message.from_text('''id 1
+ r = dns.message.from_text(
+ """id 1
flags QR
;QUESTION
www.example. IN CNAME
;AUTHORITY
example. 300 IN SOA . . 1 2 3 4 5
-''')
+"""
+ )
# passing is not going into an infinite loop in this call
result = r.resolve_chaining()
- self.assertEqual(result.canonical_name,
- dns.name.from_text('www.example.'))
+ self.assertEqual(result.canonical_name, dns.name.from_text("www.example."))
self.assertEqual(result.minimum_ttl, 5)
self.assertIsNone(result.answer)
def test_bad_text_questions(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
;QUESTION
example.
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
;QUESTION
example. IN
-''')
+"""
+ )
with self.assertRaises(dns.rdatatype.UnknownRdatatype):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
;QUESTION
example. INA
-''')
+"""
+ )
with self.assertRaises(dns.rdatatype.UnknownRdatatype):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
;QUESTION
example. IN BOGUS
-''')
+"""
+ )
def test_bad_text_rrs(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example.
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example. IN
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example. 300
-''')
+"""
+ )
with self.assertRaises(dns.rdatatype.UnknownRdatatype):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example. 30a IN A
-''')
+"""
+ )
with self.assertRaises(dns.rdatatype.UnknownRdatatype):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example. 300 INA A
-''')
+"""
+ )
with self.assertRaises(dns.exception.UnexpectedEnd):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
example. IN A
;ANSWER
example. 300 IN A
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
opcode UPDATE
;ZONE
example. IN SOA
;UPDATE
example. 300 IN A
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
opcode UPDATE
;ZONE
example. IN SOA
;UPDATE
example. 300 NONE A
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
opcode UPDATE
;ZONE
example. IN SOA
;PREREQ
example. 300 NONE A 10.0.0.1
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;ANSWER
300 IN A 10.0.0.1
-''')
+"""
+ )
with self.assertRaises(dns.exception.SyntaxError):
- dns.message.from_text('''id 1
+ dns.message.from_text(
+ """id 1
flags QR
;QUESTION
IN SOA
-''')
+"""
+ )
def test_from_wire_makes_Flag(self):
m = dns.message.from_wire(goodwire)
def test_continue_on_error(self):
good_message = dns.message.from_text(
-"""id 1234
+ """id 1234
opcode QUERY
rcode NOERROR
flags QR AA RD
www.dnspython.org. 300 IN SOA . . 1 2 3 4 4294967295
www.dnspython.org. 300 IN A 1.2.3.4
www.dnspython.org. 300 IN AAAA ::1
-""")
+"""
+ )
wire = good_message.to_wire()
# change ANCOUNT to 255
- bad_wire = wire[:6] + b'\x00\xff' + wire[8:]
+ bad_wire = wire[:6] + b"\x00\xff" + wire[8:]
# change AAAA into rdata with rdlen 0
- bad_wire = bad_wire[:-18] + b'\x00' * 2
+ bad_wire = bad_wire[:-18] + b"\x00" * 2
m = dns.message.from_wire(bad_wire, continue_on_error=True)
self.assertEqual(len(m.errors), 2)
print(m.errors)
- self.assertEqual(str(m.errors[0].exception),
- 'IPv6 addresses are 16 bytes long')
- self.assertEqual(str(m.errors[1].exception),
- 'DNS message is malformed.')
+ self.assertEqual(str(m.errors[0].exception), "IPv6 addresses are 16 bytes long")
+ self.assertEqual(str(m.errors[1].exception), "DNS message is malformed.")
expected_message = dns.message.from_text(
-"""id 1234
+ """id 1234
opcode QUERY
rcode NOERROR
flags QR AA RD
;ANSWER
www.dnspython.org. 300 IN SOA . . 1 2 3 4 4294967295
www.dnspython.org. 300 IN A 1.2.3.4
-""")
+"""
+ )
self.assertEqual(m, expected_message)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-from typing import Dict # pylint: disable=unused-import
+from typing import Dict # pylint: disable=unused-import
import copy
import operator
import pickle
class NameTestCase(unittest.TestCase):
def setUp(self):
- self.origin = dns.name.from_text('example.')
+ self.origin = dns.name.from_text("example.")
def testFromTextRel1(self):
- n = dns.name.from_text('foo.bar')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("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.assertEqual(n.labels, (b'foo', b'bar', b'example', b''))
+ n = dns.name.from_text("foo.bar", origin=self.origin)
+ self.assertEqual(n.labels, (b"foo", b"bar", b"example", b""))
def testFromTextRel3(self):
- n = dns.name.from_text('foo.bar', origin=None)
- self.assertEqual(n.labels, (b'foo', b'bar'))
+ n = dns.name.from_text("foo.bar", origin=None)
+ self.assertEqual(n.labels, (b"foo", b"bar"))
def testFromTextRel4(self):
- n = dns.name.from_text('@', origin=None)
+ n = dns.name.from_text("@", origin=None)
self.assertEqual(n, dns.name.empty)
def testFromTextRel5(self):
- n = dns.name.from_text('@', origin=self.origin)
+ n = dns.name.from_text("@", origin=self.origin)
self.assertEqual(n, self.origin)
def testFromTextAbs1(self):
- n = dns.name.from_text('foo.bar.')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("foo.bar.")
+ self.assertEqual(n.labels, (b"foo", b"bar", b""))
def testTortureFromText(self):
good = [
- 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',
- ]
+ rb".",
+ rb"a",
+ rb"a.",
+ rb"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ rb"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ rb"\000.\008.\010.\032.\046.\092.\099.\255",
+ rb"\\",
+ rb"\..\.",
+ rb"\\.\\",
+ rb'!"#%&/()=+-',
+ rb"\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\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 = [
- 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',
- ]
+ rb"..",
+ rb".a",
+ rb"\\..",
+ b"\\", # yes, we don't want the 'r' prefix!
+ rb"\0",
+ rb"\00",
+ rb"\00Z",
+ rb"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ rb"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ rb"\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\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:
dns.name.from_text(t)
def testImmutable1(self):
def bad():
self.origin.labels = ()
+
self.assertRaises(TypeError, bad)
def testImmutable2(self):
def bad():
- self.origin.labels[0] = 'foo' # type: ignore
+ self.origin.labels[0] = "foo" # type: ignore
+
self.assertRaises(TypeError, bad)
def testAbs1(self):
self.assertTrue(self.origin.is_absolute())
def testAbs4(self):
- n = dns.name.from_text('foo', origin=None)
+ n = dns.name.from_text("foo", origin=None)
self.assertFalse(n.is_absolute())
def testWild1(self):
- n = dns.name.from_text('*.foo', origin=None)
+ n = dns.name.from_text("*.foo", origin=None)
self.assertTrue(n.is_wild())
def testWild2(self):
- n = dns.name.from_text('*a.foo', origin=None)
+ n = dns.name.from_text("*a.foo", origin=None)
self.assertFalse(n.is_wild())
def testWild3(self):
- n = dns.name.from_text('a.*.foo', origin=None)
+ n = dns.name.from_text("a.*.foo", origin=None)
self.assertFalse(n.is_wild())
def testWild4(self):
self.assertFalse(dns.name.empty.is_wild())
def testHash1(self):
- n1 = dns.name.from_text('fOo.COM')
- n2 = dns.name.from_text('foo.com')
+ n1 = dns.name.from_text("fOo.COM")
+ n2 = dns.name.from_text("foo.com")
self.assertEqual(hash(n1), hash(n2))
def testCompare1(self):
- n1 = dns.name.from_text('a')
- n2 = dns.name.from_text('b')
+ n1 = dns.name.from_text("a")
+ n2 = dns.name.from_text("b")
self.assertLess(n1, n2)
self.assertLessEqual(n1, n2)
self.assertGreater(n2, n1)
self.assertGreaterEqual(n2, n1)
def testCompare2(self):
- n1 = dns.name.from_text('')
- n2 = dns.name.from_text('b')
+ n1 = dns.name.from_text("")
+ n2 = dns.name.from_text("b")
self.assertLess(n1, n2)
self.assertLessEqual(n1, n2)
self.assertGreater(n2, n1)
self.assertFalse(dns.name.root.is_subdomain(dns.name.empty))
def testSubdomain3(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(n.is_subdomain(self.origin))
def testSubdomain4(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(n.is_subdomain(dns.name.root))
def testSubdomain5(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(n.is_subdomain(n))
def testSuperdomain1(self):
self.assertFalse(dns.name.root.is_superdomain(dns.name.empty))
def testSuperdomain3(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(self.origin.is_superdomain(n))
def testSuperdomain4(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(dns.name.root.is_superdomain(n))
def testSuperdomain5(self):
- n = dns.name.from_text('foo', origin=self.origin)
+ n = dns.name.from_text("foo", origin=self.origin)
self.assertTrue(n.is_superdomain(n))
def testCanonicalize1(self):
- n = dns.name.from_text('FOO.bar', origin=self.origin)
+ n = dns.name.from_text("FOO.bar", origin=self.origin)
c = n.canonicalize()
- self.assertEqual(c.labels, (b'foo', b'bar', b'example', b''))
+ self.assertEqual(c.labels, (b"foo", b"bar", b"example", b""))
def testToText1(self):
- n = dns.name.from_text('FOO.bar', origin=self.origin)
+ n = dns.name.from_text("FOO.bar", origin=self.origin)
t = n.to_text()
- self.assertEqual(t, 'FOO.bar.example.')
+ self.assertEqual(t, "FOO.bar.example.")
def testToText2(self):
- n = dns.name.from_text('FOO.bar', origin=self.origin)
+ n = dns.name.from_text("FOO.bar", origin=self.origin)
t = n.to_text(True)
- self.assertEqual(t, 'FOO.bar.example')
+ self.assertEqual(t, "FOO.bar.example")
def testToText3(self):
- n = dns.name.from_text('FOO.bar', origin=None)
+ n = dns.name.from_text("FOO.bar", origin=None)
t = n.to_text()
- self.assertEqual(t, 'FOO.bar')
+ self.assertEqual(t, "FOO.bar")
def testToText4(self):
t = dns.name.empty.to_text()
- self.assertEqual(t, '@')
+ self.assertEqual(t, "@")
def testToText5(self):
t = dns.name.root.to_text()
- self.assertEqual(t, '.')
+ self.assertEqual(t, ".")
def testToText6(self):
- n = dns.name.from_text('FOO bar', origin=None)
+ n = dns.name.from_text("FOO bar", origin=None)
t = n.to_text()
- self.assertEqual(t, r'FOO\032bar')
+ self.assertEqual(t, r"FOO\032bar")
def testToText7(self):
- n = dns.name.from_text(r'FOO\.bar', origin=None)
+ n = dns.name.from_text(r"FOO\.bar", origin=None)
t = n.to_text()
- self.assertEqual(t, r'FOO\.bar')
+ self.assertEqual(t, r"FOO\.bar")
def testToText8(self):
- n = dns.name.from_text(r'\070OO\.bar', origin=None)
+ n = dns.name.from_text(r"\070OO\.bar", origin=None)
t = n.to_text()
- self.assertEqual(t, r'FOO\.bar')
+ self.assertEqual(t, r"FOO\.bar")
def testToText9(self):
- n = dns.name.from_text('FOO bar', origin=None)
+ n = dns.name.from_text("FOO bar", origin=None)
t = n.to_unicode()
- self.assertEqual(t, 'FOO\\032bar')
+ self.assertEqual(t, "FOO\\032bar")
def testToText10(self):
t = dns.name.empty.to_unicode()
- self.assertEqual(t, '@')
+ self.assertEqual(t, "@")
def testToText11(self):
t = dns.name.root.to_unicode()
- self.assertEqual(t, '.')
+ self.assertEqual(t, ".")
def testToText12(self):
- n = dns.name.from_text(r'a\.b.c')
+ n = dns.name.from_text(r"a\.b.c")
t = n.to_unicode()
- self.assertEqual(t, r'a\.b.c.')
+ self.assertEqual(t, r"a\.b.c.")
def testToText13(self):
- n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.')
+ n = dns.name.from_text(r"\150\151\152\153\154\155\156\157\158\159.")
t = n.to_text()
- self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.')
+ self.assertEqual(t, r"\150\151\152\153\154\155\156\157\158\159.")
def testToText14(self):
# Something that didn't start as unicode should go to escapes and not
# raise due to interpreting arbitrary binary DNS labels as UTF-8.
- n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.')
+ n = dns.name.from_text(r"\150\151\152\153\154\155\156\157\158\159.")
t = n.to_unicode()
- self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.')
+ self.assertEqual(t, r"\150\151\152\153\154\155\156\157\158\159.")
def testSlice1(self):
- n = dns.name.from_text(r'a.b.c.', origin=None)
+ n = dns.name.from_text(r"a.b.c.", origin=None)
s = n[:]
- self.assertEqual(s, (b'a', b'b', b'c', b''))
+ self.assertEqual(s, (b"a", b"b", b"c", b""))
def testSlice2(self):
- n = dns.name.from_text(r'a.b.c.', origin=None)
+ n = dns.name.from_text(r"a.b.c.", origin=None)
s = n[:2]
- self.assertEqual(s, (b'a', b'b'))
+ self.assertEqual(s, (b"a", b"b"))
def testSlice3(self):
- n = dns.name.from_text(r'a.b.c.', origin=None)
+ n = dns.name.from_text(r"a.b.c.", origin=None)
s = n[2:]
- self.assertEqual(s, (b'c', b''))
+ self.assertEqual(s, (b"c", b""))
def testEmptyLabel1(self):
def bad():
- dns.name.Name(['a', '', 'b'])
+ dns.name.Name(["a", "", "b"])
+
self.assertRaises(dns.name.EmptyLabel, bad)
def testEmptyLabel2(self):
def bad():
- dns.name.Name(['', 'b'])
+ dns.name.Name(["", "b"])
+
self.assertRaises(dns.name.EmptyLabel, bad)
def testEmptyLabel3(self):
- n = dns.name.Name(['b', ''])
+ n = dns.name.Name(["b", ""])
self.assertTrue(n)
def testLongLabel(self):
- n = dns.name.Name(['a' * 63])
+ n = dns.name.Name(["a" * 63])
self.assertTrue(n)
def testLabelTooLong(self):
def bad():
- dns.name.Name(['a' * 64, 'b'])
+ dns.name.Name(["a" * 64, "b"])
+
self.assertRaises(dns.name.LabelTooLong, bad)
def testLongName(self):
- n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 62])
+ n = dns.name.Name(["a" * 63, "a" * 63, "a" * 63, "a" * 62])
self.assertTrue(n)
def testNameTooLong(self):
def bad():
- dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 63])
+ dns.name.Name(["a" * 63, "a" * 63, "a" * 63, "a" * 63])
+
self.assertRaises(dns.name.NameTooLong, bad)
def testConcat1(self):
- n1 = dns.name.Name(['a', 'b'])
- n2 = dns.name.Name(['c', 'd'])
- e = dns.name.Name(['a', 'b', 'c', 'd'])
+ n1 = dns.name.Name(["a", "b"])
+ n2 = dns.name.Name(["c", "d"])
+ e = dns.name.Name(["a", "b", "c", "d"])
r = n1 + n2
self.assertEqual(r, e)
def testConcat2(self):
- n1 = dns.name.Name(['a', 'b'])
+ n1 = dns.name.Name(["a", "b"])
n2 = dns.name.Name([])
- e = dns.name.Name(['a', 'b'])
+ e = dns.name.Name(["a", "b"])
r = n1 + n2
self.assertEqual(r, e)
def testConcat3(self):
n1 = dns.name.Name([])
- n2 = dns.name.Name(['a', 'b'])
- e = dns.name.Name(['a', 'b'])
+ n2 = dns.name.Name(["a", "b"])
+ e = dns.name.Name(["a", "b"])
r = n1 + n2
self.assertEqual(r, e)
def testConcat4(self):
- n1 = dns.name.Name(['a', 'b', ''])
+ n1 = dns.name.Name(["a", "b", ""])
n2 = dns.name.Name([])
- e = dns.name.Name(['a', 'b', ''])
+ e = dns.name.Name(["a", "b", ""])
r = n1 + n2
self.assertEqual(r, e)
def testConcat5(self):
- n1 = dns.name.Name(['a', 'b'])
- n2 = dns.name.Name(['c', ''])
- e = dns.name.Name(['a', 'b', 'c', ''])
+ n1 = dns.name.Name(["a", "b"])
+ n2 = dns.name.Name(["c", ""])
+ e = dns.name.Name(["a", "b", "c", ""])
r = n1 + n2
self.assertEqual(r, e)
def testConcat6(self):
def bad():
- n1 = dns.name.Name(['a', 'b', ''])
- n2 = dns.name.Name(['c'])
+ n1 = dns.name.Name(["a", "b", ""])
+ n2 = dns.name.Name(["c"])
return n1 + n2
+
self.assertRaises(dns.name.AbsoluteConcatenation, bad)
def testBadEscape(self):
def bad():
- n = dns.name.from_text(r'a.b\0q1.c.')
+ n = dns.name.from_text(r"a.b\0q1.c.")
+
self.assertRaises(dns.name.BadEscape, bad)
def testDigestable1(self):
- n = dns.name.from_text('FOO.bar')
+ n = dns.name.from_text("FOO.bar")
d = n.to_digestable()
- self.assertEqual(d, b'\x03foo\x03bar\x00')
+ self.assertEqual(d, b"\x03foo\x03bar\x00")
def testDigestable2(self):
- n1 = dns.name.from_text('FOO.bar')
- n2 = dns.name.from_text('foo.BAR.')
+ n1 = dns.name.from_text("FOO.bar")
+ n2 = dns.name.from_text("foo.BAR.")
d1 = n1.to_digestable()
d2 = n2.to_digestable()
self.assertEqual(d1, d2)
def testDigestable3(self):
d = dns.name.root.to_digestable()
- self.assertEqual(d, b'\x00')
+ self.assertEqual(d, b"\x00")
def testDigestable4(self):
- n = dns.name.from_text('FOO.bar', None)
+ n = dns.name.from_text("FOO.bar", None)
d = n.to_digestable(dns.name.root)
- self.assertEqual(d, b'\x03foo\x03bar\x00')
+ self.assertEqual(d, b"\x03foo\x03bar\x00")
def testBadDigestable(self):
def bad():
- n = dns.name.from_text('FOO.bar', None)
+ n = dns.name.from_text("FOO.bar", None)
n.to_digestable()
+
self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad)
def testToWire1(self):
- n = dns.name.from_text('FOO.bar')
+ n = dns.name.from_text("FOO.bar")
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n.to_wire(f, compress)
- self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00')
+ self.assertEqual(f.getvalue(), b"\x03FOO\x03bar\x00")
def testToWire2(self):
- n = dns.name.from_text('FOO.bar')
+ n = dns.name.from_text("FOO.bar")
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n.to_wire(f, compress)
n.to_wire(f, compress)
- self.assertEqual(f.getvalue(), b'\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')
+ n1 = dns.name.from_text("FOO.bar")
+ n2 = dns.name.from_text("foo.bar")
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n1.to_wire(f, compress)
n2.to_wire(f, compress)
- self.assertEqual(f.getvalue(), b'\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')
+ n1 = dns.name.from_text("FOO.bar")
+ n2 = dns.name.from_text("a.foo.bar")
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n1.to_wire(f, compress)
n2.to_wire(f, compress)
- self.assertEqual(f.getvalue(), b'\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')
+ n1 = dns.name.from_text("FOO.bar")
+ n2 = dns.name.from_text("a.foo.bar")
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n1.to_wire(f, compress)
n2.to_wire(f, None)
- self.assertEqual(f.getvalue(),
- b'\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')
+ n = dns.name.from_text("FOO.bar")
v = n.to_wire()
- self.assertEqual(v, b'\x03FOO\x03bar\x00')
+ self.assertEqual(v, b"\x03FOO\x03bar\x00")
def testToWireRelativeNameWithOrigin(self):
- n = dns.name.from_text('FOO', None)
- o = dns.name.from_text('bar')
+ n = dns.name.from_text("FOO", None)
+ o = dns.name.from_text("bar")
v = n.to_wire(origin=o)
- self.assertEqual(v, b'\x03FOO\x03bar\x00')
+ self.assertEqual(v, b"\x03FOO\x03bar\x00")
def testToWireRelativeNameWithoutOrigin(self):
- n = dns.name.from_text('FOO', None)
+ n = dns.name.from_text("FOO", None)
+
def bad():
v = n.to_wire()
+
self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad)
def testBadToWire(self):
def bad():
- n = dns.name.from_text('FOO.bar', None)
+ n = dns.name.from_text("FOO.bar", None)
f = BytesIO()
- compress = {} # type: Dict[dns.name.Name,int]
+ compress = {} # type: Dict[dns.name.Name,int]
n.to_wire(f, compress)
+
self.assertRaises(dns.name.NeedAbsoluteNameOrOrigin, bad)
def testGiantCompressionTable(self):
f = BytesIO()
compress = {} # type: Dict[dns.name.Name,int]
# exactly 16 bytes encoded
- n = dns.name.from_text('0000000000.com.')
+ n = dns.name.from_text("0000000000.com.")
n.to_wire(f, compress)
# There are now two entries in the compression table (for the full
# name, and for the com. suffix.
self.assertEqual(len(compress), 2)
for i in range(1023):
# exactly 16 bytes encoded with compression
- n = dns.name.from_text(f'{i:013d}.com')
+ n = dns.name.from_text(f"{i:013d}.com")
n.to_wire(f, compress)
# There are now 1025 entries in the compression table with
# the last entry at offset 16368.
self.assertEqual(compress[n], 16368)
# Adding another name should not increase the size of the compression
# table, as the pointer would be at offset 16384, which is too big.
- n = dns.name.from_text('toobig.com.')
+ n = dns.name.from_text("toobig.com.")
n.to_wire(f, compress)
self.assertEqual(len(compress), 1025)
def testSplit1(self):
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
(prefix, suffix) = n.split(2)
- ep = dns.name.from_text('foo', None)
- es = dns.name.from_text('bar.', None)
+ ep = dns.name.from_text("foo", None)
+ es = dns.name.from_text("bar.", None)
self.assertEqual(prefix, ep)
self.assertEqual(suffix, es)
def testSplit2(self):
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
(prefix, suffix) = n.split(1)
- ep = dns.name.from_text('foo.bar', None)
- es = dns.name.from_text('.', None)
+ ep = dns.name.from_text("foo.bar", None)
+ es = dns.name.from_text(".", None)
self.assertEqual(prefix, ep)
self.assertEqual(suffix, es)
def testSplit3(self):
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
(prefix, suffix) = n.split(0)
- ep = dns.name.from_text('foo.bar.', None)
- es = dns.name.from_text('', None)
+ ep = dns.name.from_text("foo.bar.", None)
+ es = dns.name.from_text("", None)
self.assertEqual(prefix, ep)
self.assertEqual(suffix, es)
def testSplit4(self):
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
(prefix, suffix) = n.split(3)
- ep = dns.name.from_text('', None)
- es = dns.name.from_text('foo.bar.', None)
+ ep = dns.name.from_text("", None)
+ es = dns.name.from_text("foo.bar.", None)
self.assertEqual(prefix, ep)
self.assertEqual(suffix, es)
def testBadSplit1(self):
def bad():
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
n.split(-1)
+
self.assertRaises(ValueError, bad)
def testBadSplit2(self):
def bad():
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
n.split(4)
+
self.assertRaises(ValueError, bad)
def testRelativize1(self):
- n = dns.name.from_text('a.foo.bar.', None)
- o = dns.name.from_text('bar.', None)
- e = dns.name.from_text('a.foo', None)
+ n = dns.name.from_text("a.foo.bar.", None)
+ o = dns.name.from_text("bar.", None)
+ e = dns.name.from_text("a.foo", None)
self.assertEqual(n.relativize(o), e)
def testRelativize2(self):
- n = dns.name.from_text('a.foo.bar.', None)
+ n = dns.name.from_text("a.foo.bar.", None)
o = n
e = dns.name.empty
self.assertEqual(n.relativize(o), e)
def testRelativize3(self):
- n = dns.name.from_text('a.foo.bar.', None)
- o = dns.name.from_text('blaz.', None)
+ n = dns.name.from_text("a.foo.bar.", None)
+ o = dns.name.from_text("blaz.", None)
e = n
self.assertEqual(n.relativize(o), e)
def testRelativize4(self):
- n = dns.name.from_text('a.foo', None)
+ n = dns.name.from_text("a.foo", None)
o = dns.name.root
e = n
self.assertEqual(n.relativize(o), e)
def testDerelativize1(self):
- n = dns.name.from_text('a.foo', None)
- o = dns.name.from_text('bar.', None)
- e = dns.name.from_text('a.foo.bar.', None)
+ n = dns.name.from_text("a.foo", None)
+ o = dns.name.from_text("bar.", None)
+ e = dns.name.from_text("a.foo.bar.", None)
self.assertEqual(n.derelativize(o), e)
def testDerelativize2(self):
n = dns.name.empty
- o = dns.name.from_text('a.foo.bar.', None)
+ o = dns.name.from_text("a.foo.bar.", None)
e = o
self.assertEqual(n.derelativize(o), e)
def testDerelativize3(self):
- n = dns.name.from_text('a.foo.bar.', None)
- o = dns.name.from_text('blaz.', None)
+ n = dns.name.from_text("a.foo.bar.", None)
+ o = dns.name.from_text("blaz.", None)
e = n
self.assertEqual(n.derelativize(o), e)
def testChooseRelativity1(self):
- n = dns.name.from_text('a.foo.bar.', None)
- o = dns.name.from_text('bar.', None)
- e = dns.name.from_text('a.foo', None)
+ n = dns.name.from_text("a.foo.bar.", None)
+ o = dns.name.from_text("bar.", None)
+ e = dns.name.from_text("a.foo", None)
self.assertEqual(n.choose_relativity(o, True), e)
def testChooseRelativity2(self):
- n = dns.name.from_text('a.foo.bar.', None)
- o = dns.name.from_text('bar.', None)
+ n = dns.name.from_text("a.foo.bar.", None)
+ o = dns.name.from_text("bar.", None)
e = n
self.assertEqual(n.choose_relativity(o, False), e)
def testChooseRelativity3(self):
- n = dns.name.from_text('a.foo', None)
- o = dns.name.from_text('bar.', None)
- e = dns.name.from_text('a.foo.bar.', None)
+ n = dns.name.from_text("a.foo", None)
+ o = dns.name.from_text("bar.", None)
+ e = dns.name.from_text("a.foo.bar.", None)
self.assertEqual(n.choose_relativity(o, False), e)
def testChooseRelativity4(self):
- n = dns.name.from_text('a.foo', None)
+ n = dns.name.from_text("a.foo", None)
o = None
e = n
self.assertEqual(n.choose_relativity(o, True), e)
def testChooseRelativity5(self):
- n = dns.name.from_text('a.foo', None)
+ n = dns.name.from_text("a.foo", None)
o = None
e = n
self.assertEqual(n.choose_relativity(o, False), e)
def testChooseRelativity6(self):
- n = dns.name.from_text('a.foo.', None)
+ n = dns.name.from_text("a.foo.", None)
o = None
e = n
self.assertEqual(n.choose_relativity(o, True), e)
def testChooseRelativity7(self):
- n = dns.name.from_text('a.foo.', None)
+ n = dns.name.from_text("a.foo.", None)
o = None
e = n
self.assertEqual(n.choose_relativity(o, False), e)
def testFromWire1(self):
- w = b'\x03foo\x00\xc0\x00'
+ w = b"\x03foo\x00\xc0\x00"
(n1, cused1) = dns.name.from_wire(w, 0)
(n2, cused2) = dns.name.from_wire(w, cused1)
- en1 = dns.name.from_text('foo.')
+ en1 = dns.name.from_text("foo.")
en2 = en1
ecused1 = 5
ecused2 = 2
self.assertEqual(cused2, ecused2)
def testFromWire2(self):
- w = b'\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
(n2, cused2) = dns.name.from_wire(w, current)
current += cused2
(n3, cused3) = dns.name.from_wire(w, current)
- en1 = dns.name.from_text('foo.')
- en2 = dns.name.from_text('a.foo.')
- en3 = dns.name.from_text('b.a.foo.')
+ en1 = dns.name.from_text("foo.")
+ en2 = dns.name.from_text("a.foo.")
+ en3 = dns.name.from_text("b.a.foo.")
ecused1 = 5
ecused2 = 4
ecused3 = 4
def testBadFromWire1(self):
def bad():
- w = b'\x03foo\xc0\x04'
+ w = b"\x03foo\xc0\x04"
dns.name.from_wire(w, 0)
+
self.assertRaises(dns.name.BadPointer, bad)
def testBadFromWire2(self):
def bad():
- w = b'\x03foo\xc0\x05'
+ w = b"\x03foo\xc0\x05"
dns.name.from_wire(w, 0)
+
self.assertRaises(dns.name.BadPointer, bad)
def testBadFromWire3(self):
def bad():
- w = b'\xbffoo'
+ w = b"\xbffoo"
dns.name.from_wire(w, 0)
+
self.assertRaises(dns.name.BadLabelType, bad)
def testBadFromWire4(self):
def bad():
- w = b'\x41foo'
+ w = b"\x41foo"
dns.name.from_wire(w, 0)
+
self.assertRaises(dns.name.BadLabelType, bad)
def testParent1(self):
- n = dns.name.from_text('foo.bar.')
- self.assertEqual(n.parent(), dns.name.from_text('bar.'))
+ n = dns.name.from_text("foo.bar.")
+ self.assertEqual(n.parent(), dns.name.from_text("bar."))
self.assertEqual(n.parent().parent(), dns.name.root)
def testParent2(self):
- n = dns.name.from_text('foo.bar', None)
- self.assertEqual(n.parent(), dns.name.from_text('bar', None))
+ n = dns.name.from_text("foo.bar", None)
+ self.assertEqual(n.parent(), dns.name.from_text("bar", None))
self.assertEqual(n.parent().parent(), dns.name.empty)
def testParent3(self):
def bad():
n = dns.name.root
n.parent()
+
self.assertRaises(dns.name.NoParent, bad)
def testParent4(self):
def bad():
n = dns.name.empty
n.parent()
+
self.assertRaises(dns.name.NoParent, bad)
def testFromUnicode1(self):
- n = dns.name.from_text('foo.bar')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("foo.bar")
+ self.assertEqual(n.labels, (b"foo", b"bar", b""))
def testFromUnicode2(self):
- n = dns.name.from_text('foo\u1234bar.bar')
- self.assertEqual(n.labels, (b'xn--foobar-r5z', b'bar', b''))
+ n = dns.name.from_text("foo\u1234bar.bar")
+ self.assertEqual(n.labels, (b"xn--foobar-r5z", b"bar", b""))
def testFromUnicodeAlternateDot1(self):
- n = dns.name.from_text('foo\u3002bar')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("foo\u3002bar")
+ self.assertEqual(n.labels, (b"foo", b"bar", b""))
def testFromUnicodeAlternateDot2(self):
- n = dns.name.from_text('foo\uff0ebar')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("foo\uff0ebar")
+ self.assertEqual(n.labels, (b"foo", b"bar", b""))
def testFromUnicodeAlternateDot3(self):
- n = dns.name.from_text('foo\uff61bar')
- self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ n = dns.name.from_text("foo\uff61bar")
+ self.assertEqual(n.labels, (b"foo", b"bar", b""))
def testFromUnicodeRoot(self):
- n = dns.name.from_text('.')
- self.assertEqual(n.labels, (b'',))
+ n = dns.name.from_text(".")
+ self.assertEqual(n.labels, (b"",))
def testFromUnicodeAlternateRoot1(self):
- n = dns.name.from_text('\u3002')
- self.assertEqual(n.labels, (b'',))
+ n = dns.name.from_text("\u3002")
+ self.assertEqual(n.labels, (b"",))
def testFromUnicodeAlternateRoot2(self):
- n = dns.name.from_text('\uff0e')
- self.assertEqual(n.labels, (b'',))
+ n = dns.name.from_text("\uff0e")
+ self.assertEqual(n.labels, (b"",))
def testFromUnicodeAlternateRoot3(self):
- n = dns.name.from_text('\uff61')
- self.assertEqual(n.labels, (b'', ))
+ n = dns.name.from_text("\uff61")
+ self.assertEqual(n.labels, (b"",))
def testFromUnicodeIDNA2003Explicit(self):
- t = 'Königsgäßchen'
+ t = "Königsgäßchen"
e = dns.name.from_unicode(t, idna_codec=dns.name.IDNA_2003)
- self.assertEqual(str(e), 'xn--knigsgsschen-lcb0w.')
+ self.assertEqual(str(e), "xn--knigsgsschen-lcb0w.")
def testFromUnicodeIDNA2003Default(self):
- t = 'Königsgäßchen'
+ t = "Königsgäßchen"
e = dns.name.from_unicode(t)
- self.assertEqual(str(e), 'xn--knigsgsschen-lcb0w.')
+ self.assertEqual(str(e), "xn--knigsgsschen-lcb0w.")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testFromUnicodeIDNA2008(self):
- t = 'Königsgäßchen'
+ t = "Königsgäßchen"
+
def bad():
codec = dns.name.IDNA_2008_Strict
return dns.name.from_unicode(t, idna_codec=codec)
+
self.assertRaises(dns.name.IDNAException, bad)
e1 = dns.name.from_unicode(t, idna_codec=dns.name.IDNA_2008)
- self.assertEqual(str(e1), 'xn--knigsgchen-b4a3dun.')
+ self.assertEqual(str(e1), "xn--knigsgchen-b4a3dun.")
c2 = dns.name.IDNA_2008_Transitional
e2 = dns.name.from_unicode(t, idna_codec=c2)
- self.assertEqual(str(e2), 'xn--knigsgsschen-lcb0w.')
+ self.assertEqual(str(e2), "xn--knigsgsschen-lcb0w.")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testFromUnicodeIDNA2008Mixed(self):
# the IDN rules for names are very restrictive, disallowing
# practical names like '_sip._tcp.Königsgäßchen'. Dnspython
# has a "practical" mode which permits labels which are purely
# ASCII to go straight through, and thus not invalid useful
# things in the real world.
- t = '_sip._tcp.Königsgäßchen'
+ t = "_sip._tcp.Königsgäßchen"
+
def bad1():
codec = dns.name.IDNA_2008_Strict
return dns.name.from_unicode(t, idna_codec=codec)
+
def bad2():
codec = dns.name.IDNA_2008_UTS_46
return dns.name.from_unicode(t, idna_codec=codec)
+
def bad3():
codec = dns.name.IDNA_2008_Transitional
return dns.name.from_unicode(t, idna_codec=codec)
+
self.assertRaises(dns.name.IDNAException, bad1)
self.assertRaises(dns.name.IDNAException, bad2)
self.assertRaises(dns.name.IDNAException, bad3)
- e = dns.name.from_unicode(t,
- idna_codec=dns.name.IDNA_2008_Practical)
- self.assertEqual(str(e), '_sip._tcp.xn--knigsgchen-b4a3dun.')
+ e = dns.name.from_unicode(t, idna_codec=dns.name.IDNA_2008_Practical)
+ self.assertEqual(str(e), "_sip._tcp.xn--knigsgchen-b4a3dun.")
def testFromUnicodeEscapes(self):
- n = dns.name.from_unicode(r'\097.\098.\099.')
+ n = dns.name.from_unicode(r"\097.\098.\099.")
t = n.to_unicode()
- self.assertEqual(t, 'a.b.c.')
+ self.assertEqual(t, "a.b.c.")
def testToUnicode1(self):
- n = dns.name.from_text('foo.bar')
+ n = dns.name.from_text("foo.bar")
s = n.to_unicode()
- self.assertEqual(s, 'foo.bar.')
+ self.assertEqual(s, "foo.bar.")
def testToUnicode2(self):
- n = dns.name.from_text('foo\u1234bar.bar')
+ n = dns.name.from_text("foo\u1234bar.bar")
s = n.to_unicode()
- self.assertEqual(s, 'foo\u1234bar.bar.')
+ self.assertEqual(s, "foo\u1234bar.bar.")
def testToUnicode3(self):
- n = dns.name.from_text('foo.bar')
+ n = dns.name.from_text("foo.bar")
s = n.to_unicode()
- self.assertEqual(s, 'foo.bar.')
+ self.assertEqual(s, "foo.bar.")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testToUnicode4(self):
- n = dns.name.from_text('ドメイン.テスト',
- idna_codec=dns.name.IDNA_2008)
+ n = dns.name.from_text("ドメイン.テスト", idna_codec=dns.name.IDNA_2008)
s = n.to_unicode()
- self.assertEqual(str(n), 'xn--eckwd4c7c.xn--zckzah.')
- self.assertEqual(s, 'ドメイン.テスト.')
+ self.assertEqual(str(n), "xn--eckwd4c7c.xn--zckzah.")
+ self.assertEqual(s, "ドメイン.テスト.")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testToUnicode5(self):
# Exercise UTS 46 remapping in decode. This doesn't normally happen
# as you can see from us having to instantiate the codec as
# transitional with strict decoding, not one of our usual choices.
codec = dns.name.IDNA2008Codec(True, True, False, True)
- n = dns.name.from_text('xn--gro-7ka.com')
- self.assertEqual(n.to_unicode(idna_codec=codec),
- 'gross.com.')
+ n = dns.name.from_text("xn--gro-7ka.com")
+ self.assertEqual(n.to_unicode(idna_codec=codec), "gross.com.")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testToUnicode6(self):
# Test strict 2008 decoding without UTS 46
- n = dns.name.from_text('xn--gro-7ka.com')
- self.assertEqual(n.to_unicode(idna_codec=dns.name.IDNA_2008_Strict),
- 'groß.com.')
+ n = dns.name.from_text("xn--gro-7ka.com")
+ self.assertEqual(
+ n.to_unicode(idna_codec=dns.name.IDNA_2008_Strict), "groß.com."
+ )
def testDefaultDecodeIsJustPunycode(self):
# groß.com. in IDNA2008 form, pre-encoded.
- n = dns.name.from_text('xn--gro-7ka.com')
+ n = dns.name.from_text("xn--gro-7ka.com")
# output using default codec which just decodes the punycode and
# doesn't test for IDNA2003 or IDNA2008.
- self.assertEqual(n.to_unicode(), 'groß.com.')
+ self.assertEqual(n.to_unicode(), "groß.com.")
def testStrictINDA2003Decode(self):
# groß.com. in IDNA2008 form, pre-encoded.
- n = dns.name.from_text('xn--gro-7ka.com')
+ n = dns.name.from_text("xn--gro-7ka.com")
+
def bad():
# This throws in IDNA2003 because it doesn't "round trip".
n.to_unicode(idna_codec=dns.name.IDNA_2003_Strict)
+
self.assertRaises(dns.name.IDNAException, bad)
def testINDA2008Decode(self):
# groß.com. in IDNA2008 form, pre-encoded.
- n = dns.name.from_text('xn--gro-7ka.com')
- self.assertEqual(n.to_unicode(idna_codec=dns.name.IDNA_2008),
- 'groß.com.')
+ n = dns.name.from_text("xn--gro-7ka.com")
+ self.assertEqual(n.to_unicode(idna_codec=dns.name.IDNA_2008), "groß.com.")
def testToUnicodeOmitFinalDot(self):
# groß.com. in IDNA2008 form, pre-encoded.
- n = dns.name.from_text('xn--gro-7ka.com')
- self.assertEqual(n.to_unicode(True, dns.name.IDNA_2008),
- 'groß.com')
+ n = dns.name.from_text("xn--gro-7ka.com")
+ self.assertEqual(n.to_unicode(True, dns.name.IDNA_2008), "groß.com")
def testIDNA2003Misc(self):
- self.assertEqual(dns.name.IDNA_2003.encode(''), b'')
- self.assertRaises(dns.name.LabelTooLong,
- lambda: dns.name.IDNA_2003.encode('x' * 64))
-
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ self.assertEqual(dns.name.IDNA_2003.encode(""), b"")
+ self.assertRaises(
+ dns.name.LabelTooLong, lambda: dns.name.IDNA_2003.encode("x" * 64)
+ )
+
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testIDNA2008Misc(self):
- self.assertEqual(dns.name.IDNA_2008.encode(''), b'')
- self.assertRaises(dns.name.LabelTooLong,
- lambda: dns.name.IDNA_2008.encode('x' * 64))
- self.assertRaises(dns.name.LabelTooLong,
- lambda: dns.name.IDNA_2008.encode('groß' + 'x' * 60))
+ self.assertEqual(dns.name.IDNA_2008.encode(""), b"")
+ self.assertRaises(
+ dns.name.LabelTooLong, lambda: dns.name.IDNA_2008.encode("x" * 64)
+ )
+ self.assertRaises(
+ dns.name.LabelTooLong, lambda: dns.name.IDNA_2008.encode("groß" + "x" * 60)
+ )
def testReverseIPv4(self):
- e = dns.name.from_text('1.0.0.127.in-addr.arpa.')
- n = dns.reversename.from_address('127.0.0.1')
+ e = dns.name.from_text("1.0.0.127.in-addr.arpa.")
+ n = dns.reversename.from_address("127.0.0.1")
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')
+ 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.assertEqual(e, n)
def testReverseIPv6MappedIpv4(self):
- e = dns.name.from_text('1.0.0.127.in-addr.arpa.')
- n = dns.reversename.from_address('::ffff:127.0.0.1')
+ e = dns.name.from_text("1.0.0.127.in-addr.arpa.")
+ n = dns.reversename.from_address("::ffff:127.0.0.1")
self.assertEqual(e, n)
def testBadReverseIPv4(self):
def bad():
- dns.reversename.from_address('127.0.foo.1')
+ dns.reversename.from_address("127.0.foo.1")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testBadReverseIPv6(self):
def bad():
- dns.reversename.from_address('::1::1')
+ dns.reversename.from_address("::1::1")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testReverseIPv4AlternateOrigin(self):
- e = dns.name.from_text('1.0.0.127.foo.bar.')
- origin = dns.name.from_text('foo.bar')
- n = dns.reversename.from_address('127.0.0.1', v4_origin=origin)
+ e = dns.name.from_text("1.0.0.127.foo.bar.")
+ origin = dns.name.from_text("foo.bar")
+ n = dns.reversename.from_address("127.0.0.1", v4_origin=origin)
self.assertEqual(e, n)
def testReverseIPv6AlternateOrigin(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.foo.bar.')
- origin = dns.name.from_text('foo.bar')
- n = dns.reversename.from_address('::1', v6_origin=origin)
+ 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.foo.bar."
+ )
+ origin = dns.name.from_text("foo.bar")
+ n = dns.reversename.from_address("::1", v6_origin=origin)
self.assertEqual(e, n)
def testForwardIPv4(self):
- n = dns.name.from_text('1.0.0.127.in-addr.arpa.')
- e = '127.0.0.1'
+ n = dns.name.from_text("1.0.0.127.in-addr.arpa.")
+ e = "127.0.0.1"
text = dns.reversename.to_address(n)
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'
+ 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"
text = dns.reversename.to_address(n)
self.assertEqual(text, e)
def testForwardIPv4AlternateOrigin(self):
- n = dns.name.from_text('1.0.0.127.foo.bar.')
- e = '127.0.0.1'
- origin = dns.name.from_text('foo.bar')
+ n = dns.name.from_text("1.0.0.127.foo.bar.")
+ e = "127.0.0.1"
+ origin = dns.name.from_text("foo.bar")
text = dns.reversename.to_address(n, v4_origin=origin)
self.assertEqual(text, e)
def testForwardIPv6AlternateOrigin(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.foo.bar.')
- e = '::1'
- origin = dns.name.from_text('foo.bar')
+ 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.foo.bar."
+ )
+ e = "::1"
+ origin = dns.name.from_text("foo.bar")
text = dns.reversename.to_address(n, v6_origin=origin)
self.assertEqual(text, e)
def testUnknownReverseOrigin(self):
- n = dns.name.from_text('1.2.3.4.unknown.')
+ n = dns.name.from_text("1.2.3.4.unknown.")
with self.assertRaises(dns.exception.SyntaxError):
dns.reversename.to_address(n)
def testE164ToEnum(self):
- text = '+1 650 555 1212'
- e = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
+ text = "+1 650 555 1212"
+ e = dns.name.from_text("2.1.2.1.5.5.5.0.5.6.1.e164.arpa.")
n = dns.e164.from_e164(text)
self.assertEqual(n, e)
def testEnumToE164(self):
- n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
- e = '+16505551212'
+ n = dns.name.from_text("2.1.2.1.5.5.5.0.5.6.1.e164.arpa.")
+ e = "+16505551212"
text = dns.e164.to_e164(n)
self.assertEqual(text, e)
def testBadEnumToE164(self):
- n = dns.name.from_text('2.1.2.q.5.5.5.0.5.6.1.e164.arpa.')
- self.assertRaises(dns.exception.SyntaxError,
- lambda: dns.e164.to_e164(n))
+ n = dns.name.from_text("2.1.2.q.5.5.5.0.5.6.1.e164.arpa.")
+ self.assertRaises(dns.exception.SyntaxError, lambda: dns.e164.to_e164(n))
def test_incompatible_relations(self):
- n1 = dns.name.from_text('example')
- n2 = 'abc'
+ n1 = dns.name.from_text("example")
+ n2 = "abc"
for oper in [operator.lt, operator.le, operator.ge, operator.gt]:
self.assertRaises(TypeError, lambda: oper(n1, n2))
self.assertFalse(n1 == n2)
self.assertTrue(n1 != n2)
def testFromUnicodeSimpleEscape(self):
- n = dns.name.from_unicode(r'a.\b')
- e = dns.name.from_unicode(r'a.b')
+ n = dns.name.from_unicode(r"a.\b")
+ e = dns.name.from_unicode(r"a.b")
self.assertEqual(n, e)
def testFromUnicodeBadEscape(self):
def bad1():
- n = dns.name.from_unicode(r'a.b\0q1.c.')
+ n = dns.name.from_unicode(r"a.b\0q1.c.")
+
self.assertRaises(dns.name.BadEscape, bad1)
+
def bad2():
- n = dns.name.from_unicode(r'a.b\0')
+ n = dns.name.from_unicode(r"a.b\0")
+
self.assertRaises(dns.name.BadEscape, bad2)
def testFromUnicodeNotString(self):
def bad():
- dns.name.from_unicode(b'123') # type: ignore
+ dns.name.from_unicode(b"123") # type: ignore
+
self.assertRaises(ValueError, bad)
def testFromUnicodeBadOrigin(self):
def bad():
- dns.name.from_unicode('example', 123) # type: ignore
+ dns.name.from_unicode("example", 123) # type: ignore
+
self.assertRaises(ValueError, bad)
def testFromUnicodeEmptyLabel(self):
def bad():
- dns.name.from_unicode('a..b.example')
+ dns.name.from_unicode("a..b.example")
+
self.assertRaises(dns.name.EmptyLabel, bad)
def testFromUnicodeEmptyName(self):
- self.assertEqual(dns.name.from_unicode('@', None), dns.name.empty)
+ self.assertEqual(dns.name.from_unicode("@", None), dns.name.empty)
def testFromTextNotString(self):
def bad():
dns.name.from_text(123) # type: ignore
+
self.assertRaises(ValueError, bad)
def testFromTextBadOrigin(self):
def bad():
- dns.name.from_text('example', 123) # type: ignore
+ dns.name.from_text("example", 123) # type: ignore
+
self.assertRaises(ValueError, bad)
def testFromWireNotBytes(self):
def bad():
dns.name.from_wire(123, 0) # type: ignore
+
self.assertRaises(ValueError, bad)
def testBadPunycode(self):
c = dns.name.IDNACodec()
with self.assertRaises(dns.name.IDNAException):
- c.decode(b'xn--0000h')
+ c.decode(b"xn--0000h")
def testRootLabel2003StrictDecode(self):
c = dns.name.IDNA_2003_Strict
- self.assertEqual(c.decode(b''), '')
+ self.assertEqual(c.decode(b""), "")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testRootLabel2008StrictDecode(self):
c = dns.name.IDNA_2008_Strict
- self.assertEqual(c.decode(b''), '')
+ self.assertEqual(c.decode(b""), "")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testCodecNotFoundRaises(self):
dns.name.have_idna_2008 = False
with self.assertRaises(dns.name.NoIDNA2008):
c = dns.name.IDNA2008Codec()
- c.encode('Königsgäßchen')
+ c.encode("Königsgäßchen")
with self.assertRaises(dns.name.NoIDNA2008):
c = dns.name.IDNA2008Codec(strict_decode=True)
- c.decode(b'xn--eckwd4c7c.xn--zckzah.')
+ c.decode(b"xn--eckwd4c7c.xn--zckzah.")
dns.name.have_idna_2008 = True
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testBadPunycodeStrict2008(self):
c = dns.name.IDNA2008Codec(strict_decode=True)
with self.assertRaises(dns.name.IDNAException):
- c.decode(b'xn--0000h')
+ c.decode(b"xn--0000h")
def testRelativizeSubtractionSyntax(self):
- n = dns.name.from_text('foo.example.')
- o = dns.name.from_text('example.')
- e = dns.name.from_text('foo', None)
+ n = dns.name.from_text("foo.example.")
+ o = dns.name.from_text("example.")
+ e = dns.name.from_text("foo", None)
self.assertEqual(n - o, e)
def testCopy(self):
- n1 = dns.name.from_text('foo.example.')
+ n1 = dns.name.from_text("foo.example.")
n2 = copy.copy(n1)
self.assertTrue(n1 is not n2)
# the Name constructor always copies labels, so there is no
self.assertTrue(l is n2[i])
def testDeepCopy(self):
- n1 = dns.name.from_text('foo.example.')
+ n1 = dns.name.from_text("foo.example.")
n2 = copy.deepcopy(n1)
self.assertTrue(n1 is not n2)
self.assertTrue(n1.labels is not n2.labels)
self.assertTrue(l is n2[i])
def testNoAttributeDeletion(self):
- n = dns.name.from_text('foo.example.')
+ n = dns.name.from_text("foo.example.")
with self.assertRaises(TypeError):
del n.labels
def testUnicodeEscapify(self):
- n = dns.name.from_unicode('Königsgäßchen;\ttext')
- self.assertEqual(n.to_unicode(), 'königsgässchen\\;\\009text.')
+ n = dns.name.from_unicode("Königsgäßchen;\ttext")
+ self.assertEqual(n.to_unicode(), "königsgässchen\\;\\009text.")
def test_pickle(self):
- n1 = dns.name.from_text('foo.example')
+ n1 = dns.name.from_text("foo.example")
p = pickle.dumps(n1)
n2 = pickle.loads(p)
self.assertEqual(n1, n2)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
import dns.name
import dns.namedict
-class NameTestCase(unittest.TestCase):
+class NameTestCase(unittest.TestCase):
def setUp(self):
self.ndict = dns.namedict.NameDict()
- n1 = dns.name.from_text('foo.bar.')
- n2 = dns.name.from_text('bar.')
+ n1 = dns.name.from_text("foo.bar.")
+ n2 = dns.name.from_text("bar.")
self.ndict[n1] = 1
self.ndict[n2] = 2
self.rndict = dns.namedict.NameDict()
- n1 = dns.name.from_text('foo.bar', None)
- n2 = dns.name.from_text('bar', None)
+ n1 = dns.name.from_text("foo.bar", None)
+ n2 = dns.name.from_text("bar", None)
self.rndict[n1] = 1
self.rndict[n2] = 2
self.assertEqual(self.ndict.max_depth, 3)
def testLookup1(self):
- k = dns.name.from_text('foo.bar.')
+ k = dns.name.from_text("foo.bar.")
self.assertEqual(self.ndict[k], 1)
def testLookup2(self):
- k = dns.name.from_text('foo.bar.')
+ k = dns.name.from_text("foo.bar.")
self.assertEqual(self.ndict.get_deepest_match(k)[1], 1)
def testLookup3(self):
- k = dns.name.from_text('a.b.c.foo.bar.')
+ k = dns.name.from_text("a.b.c.foo.bar.")
self.assertEqual(self.ndict.get_deepest_match(k)[1], 1)
def testLookup4(self):
- k = dns.name.from_text('a.b.c.bar.')
+ k = dns.name.from_text("a.b.c.bar.")
self.assertEqual(self.ndict.get_deepest_match(k)[1], 2)
def testLookup5(self):
def bad():
- n = dns.name.from_text('a.b.c.')
+ n = dns.name.from_text("a.b.c.")
self.ndict.get_deepest_match(n)
+
self.assertRaises(KeyError, bad)
def testLookup6(self):
def bad():
self.ndict.get_deepest_match(dns.name.empty)
+
self.assertRaises(KeyError, bad)
def testLookup7(self):
self.ndict[dns.name.empty] = 100
- n = dns.name.from_text('a.b.c.')
+ n = dns.name.from_text("a.b.c.")
v = self.ndict.get_deepest_match(n)[1]
self.assertEqual(v, 100)
def testLookup8(self):
def bad():
- self.ndict['foo'] = 100
+ self.ndict["foo"] = 100
+
self.assertRaises(ValueError, bad)
def testRelDepth(self):
self.assertEqual(self.rndict.max_depth, 2)
def testRelLookup1(self):
- k = dns.name.from_text('foo.bar', None)
+ k = dns.name.from_text("foo.bar", None)
self.assertEqual(self.rndict[k], 1)
def testRelLookup2(self):
- k = dns.name.from_text('foo.bar', None)
+ k = dns.name.from_text("foo.bar", None)
self.assertEqual(self.rndict.get_deepest_match(k)[1], 1)
def testRelLookup3(self):
- k = dns.name.from_text('a.b.c.foo.bar', None)
+ k = dns.name.from_text("a.b.c.foo.bar", None)
self.assertEqual(self.rndict.get_deepest_match(k)[1], 1)
def testRelLookup4(self):
- k = dns.name.from_text('a.b.c.bar', None)
+ k = dns.name.from_text("a.b.c.bar", None)
self.assertEqual(self.rndict.get_deepest_match(k)[1], 2)
def testRelLookup7(self):
self.rndict[dns.name.empty] = 100
- n = dns.name.from_text('a.b.c', None)
+ n = dns.name.from_text("a.b.c", None)
v = self.rndict.get_deepest_match(n)[1]
self.assertEqual(v, 100)
def test_max_depth_increases(self):
- n = dns.name.from_text('a.foo.bar.')
+ n = dns.name.from_text("a.foo.bar.")
self.assertEqual(self.ndict.max_depth, 3)
self.ndict[n] = 1
self.assertEqual(self.ndict.max_depth, 4)
def test_delete_no_max_depth_change(self):
self.assertEqual(self.ndict.max_depth, 3)
- n = dns.name.from_text('bar.')
+ n = dns.name.from_text("bar.")
del self.ndict[n]
self.assertEqual(self.ndict.max_depth, 3)
self.assertEqual(self.ndict.get(n), None)
def test_delete_max_depth_changes(self):
self.assertEqual(self.ndict.max_depth, 3)
- n = dns.name.from_text('foo.bar.')
+ n = dns.name.from_text("foo.bar.")
del self.ndict[n]
self.assertEqual(self.ndict.max_depth, 2)
self.assertEqual(self.ndict.get(n), None)
def test_delete_multiple_max_depth_changes(self):
self.assertEqual(self.ndict.max_depth, 3)
- nr = dns.name.from_text('roo.')
+ nr = dns.name.from_text("roo.")
self.ndict[nr] = 1
- nf = dns.name.from_text('foo.bar.')
- nb = dns.name.from_text('bar.bar.')
+ nf = dns.name.from_text("foo.bar.")
+ nb = dns.name.from_text("bar.bar.")
self.ndict[nb] = 1
self.assertEqual(self.ndict.max_depth, 3)
self.assertEqual(self.ndict.max_depth_items, 2)
self.assertEqual(self.ndict.get(nb), None)
def test_iter(self):
- nf = dns.name.from_text('foo.bar.')
- nb = dns.name.from_text('bar.')
+ nf = dns.name.from_text("foo.bar.")
+ nb = dns.name.from_text("bar.")
keys = set([x for x in self.ndict])
self.assertEqual(len(keys), 2)
self.assertTrue(nf in keys)
self.assertEqual(len(self.ndict), 2)
def test_haskey(self):
- nf = dns.name.from_text('foo.bar.')
- nb = dns.name.from_text('bar.')
- nx = dns.name.from_text('x.')
+ nf = dns.name.from_text("foo.bar.")
+ nb = dns.name.from_text("bar.")
+ nx = dns.name.from_text("x.")
self.assertTrue(self.ndict.has_key(nf))
self.assertTrue(self.ndict.has_key(nb))
self.assertFalse(self.ndict.has_key(nx))
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
import dns.rdtypes.ANY.TXT
import dns.ttl
+
class NSEC3TestCase(unittest.TestCase):
def test_NSEC3_bitmap(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3,
- u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA TYPE65534")
- bitmap = bytearray(b'\0' * 32)
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.NSEC3,
+ "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA TYPE65534",
+ )
+ bitmap = bytearray(b"\0" * 32)
bitmap[31] = bitmap[31] | 2
- self.assertEqual(rdata.windows, ((0, b'@'),
- (1, b'@'), # CAA = 257
- (255, bitmap)
- ))
+ self.assertEqual(
+ rdata.windows, ((0, b"@"), (1, b"@"), (255, bitmap)) # CAA = 257
+ )
def test_NSEC3_bad_bitmaps(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3,
- u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA")
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.NSEC3,
+ "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA",
+ )
with self.assertRaises(dns.exception.FormError):
copy = bytearray(rdata.to_wire())
copy[-3] = 0
- dns.rdata.from_wire('IN', 'NSEC3', copy, 0, len(copy))
+ dns.rdata.from_wire("IN", "NSEC3", copy, 0, len(copy))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
"aabbccdd",
12,
"0p9mhaveqvm6t7vbl5lop2u3t2rp3tom",
- dnssec.NSEC3Hash.SHA1
+ dnssec.NSEC3Hash.SHA1,
),
("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", "SHA1"),
- ("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", "sha1")
+ ("example", "aabbccdd", 12, "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom", "sha1"),
]
def test_hash_function(self):
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',
- '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4',
- '1.2.3.4.']
+v4_bad_addrs = [
+ "256.1.1.1",
+ "1.1.1",
+ "1.1.1.1.1",
+ "+1.1.1.1",
+ "1.1.1.1+",
+ "1..2.3.4",
+ ".1.2.3.4",
+ "1.2.3.4.",
+]
-class NtoAAtoNTestCase(unittest.TestCase):
+class NtoAAtoNTestCase(unittest.TestCase):
def test_aton1(self):
- a = aton6('::')
- self.assertEqual(a, b'\x00' * 16)
+ a = aton6("::")
+ self.assertEqual(a, b"\x00" * 16)
def test_aton2(self):
- a = aton6('::1')
- self.assertEqual(a, b'\x00' * 15 + b'\x01')
+ a = aton6("::1")
+ self.assertEqual(a, b"\x00" * 15 + b"\x01")
def test_aton3(self):
- a = aton6('::10.0.0.1')
- self.assertEqual(a, b'\x00' * 12 + b'\x0a\x00\x00\x01')
+ a = aton6("::10.0.0.1")
+ self.assertEqual(a, b"\x00" * 12 + b"\x0a\x00\x00\x01")
def test_aton4(self):
- a = aton6('abcd::dcba')
- self.assertEqual(a, b'\xab\xcd' + b'\x00' * 12 + b'\xdc\xba')
+ a = aton6("abcd::dcba")
+ self.assertEqual(a, b"\xab\xcd" + b"\x00" * 12 + b"\xdc\xba")
def test_aton5(self):
- a = aton6('1:2:3:4:5:6:7:8')
- self.assertEqual(a,
- binascii.unhexlify(b'00010002000300040005000600070008'))
+ a = aton6("1:2:3:4:5:6:7:8")
+ self.assertEqual(a, binascii.unhexlify(b"00010002000300040005000600070008"))
def test_bad_aton1(self):
def bad():
- aton6('abcd:dcba')
+ aton6("abcd:dcba")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_bad_aton2(self):
def bad():
- aton6('abcd::dcba::1')
+ aton6("abcd::dcba::1")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_bad_aton3(self):
def bad():
- aton6('1:2:3:4:5:6:7:8:9')
+ aton6("1:2:3:4:5:6:7:8:9")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_bad_aton4(self):
def bad():
- aton4('001.002.003.004')
+ aton4("001.002.003.004")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_aton6(self):
- a = aton6('::')
- self.assertEqual(a, b'\x00' * 16)
+ a = aton6("::")
+ self.assertEqual(a, b"\x00" * 16)
def test_aton7(self):
- a = aton6('::1')
- self.assertEqual(a, b'\x00' * 15 + b'\x01')
+ a = aton6("::1")
+ self.assertEqual(a, b"\x00" * 15 + b"\x01")
def test_aton8(self):
- a = aton6('::10.0.0.1')
- self.assertEqual(a, b'\x00' * 12 + b'\x0a\x00\x00\x01')
+ a = aton6("::10.0.0.1")
+ self.assertEqual(a, b"\x00" * 12 + b"\x0a\x00\x00\x01")
def test_aton9(self):
- a = aton6('abcd::dcba')
- self.assertEqual(a, b'\xab\xcd' + b'\x00' * 12 + b'\xdc\xba')
+ a = aton6("abcd::dcba")
+ self.assertEqual(a, b"\xab\xcd" + b"\x00" * 12 + b"\xdc\xba")
def test_ntoa1(self):
- b = binascii.unhexlify(b'00010002000300040005000600070008')
+ b = binascii.unhexlify(b"00010002000300040005000600070008")
t = ntoa6(b)
- self.assertEqual(t, '1:2:3:4:5:6:7:8')
+ self.assertEqual(t, "1:2:3:4:5:6:7:8")
def test_ntoa2(self):
- b = b'\x00' * 16
+ b = b"\x00" * 16
t = ntoa6(b)
- self.assertEqual(t, '::')
+ self.assertEqual(t, "::")
def test_ntoa3(self):
- b = b'\x00' * 15 + b'\x01'
+ b = b"\x00" * 15 + b"\x01"
t = ntoa6(b)
- self.assertEqual(t, '::1')
+ self.assertEqual(t, "::1")
def test_ntoa4(self):
- b = b'\x80' + b'\x00' * 15
+ b = b"\x80" + b"\x00" * 15
t = ntoa6(b)
- self.assertEqual(t, '8000::')
+ self.assertEqual(t, "8000::")
def test_ntoa5(self):
- b = b'\x01\xcd' + b'\x00' * 12 + b'\x03\xef'
+ b = b"\x01\xcd" + b"\x00" * 12 + b"\x03\xef"
t = ntoa6(b)
- self.assertEqual(t, '1cd::3ef')
+ self.assertEqual(t, "1cd::3ef")
def test_ntoa6(self):
- b = binascii.unhexlify(b'ffff00000000ffff000000000000ffff')
+ b = binascii.unhexlify(b"ffff00000000ffff000000000000ffff")
t = ntoa6(b)
- self.assertEqual(t, 'ffff:0:0:ffff::ffff')
+ self.assertEqual(t, "ffff:0:0:ffff::ffff")
def test_ntoa7(self):
- b = binascii.unhexlify(b'00000000ffff000000000000ffffffff')
+ b = binascii.unhexlify(b"00000000ffff000000000000ffffffff")
t = ntoa6(b)
- self.assertEqual(t, '0:0:ffff::ffff:ffff')
+ self.assertEqual(t, "0:0:ffff::ffff:ffff")
def test_ntoa8(self):
- b = binascii.unhexlify(b'ffff0000ffff00000000ffff00000000')
+ b = binascii.unhexlify(b"ffff0000ffff00000000ffff00000000")
t = ntoa6(b)
- self.assertEqual(t, 'ffff:0:ffff::ffff:0:0')
+ self.assertEqual(t, "ffff:0:ffff::ffff:0:0")
def test_ntoa9(self):
- b = binascii.unhexlify(b'0000000000000000000000000a000001')
+ b = binascii.unhexlify(b"0000000000000000000000000a000001")
t = ntoa6(b)
- self.assertEqual(t, '::10.0.0.1')
+ self.assertEqual(t, "::10.0.0.1")
def test_ntoa10(self):
- b = binascii.unhexlify(b'0000000000000000000000010a000001')
+ b = binascii.unhexlify(b"0000000000000000000000010a000001")
t = ntoa6(b)
- self.assertEqual(t, '::1:a00:1')
+ self.assertEqual(t, "::1:a00:1")
def test_ntoa11(self):
- b = binascii.unhexlify(b'00000000000000000000ffff0a000001')
+ b = binascii.unhexlify(b"00000000000000000000ffff0a000001")
t = ntoa6(b)
- self.assertEqual(t, '::ffff:10.0.0.1')
+ self.assertEqual(t, "::ffff:10.0.0.1")
def test_ntoa12(self):
- b = binascii.unhexlify(b'000000000000000000000000ffffffff')
+ b = binascii.unhexlify(b"000000000000000000000000ffffffff")
t = ntoa6(b)
- self.assertEqual(t, '::255.255.255.255')
+ self.assertEqual(t, "::255.255.255.255")
def test_ntoa13(self):
- b = binascii.unhexlify(b'00000000000000000000ffffffffffff')
+ b = binascii.unhexlify(b"00000000000000000000ffffffffffff")
t = ntoa6(b)
- self.assertEqual(t, '::ffff:255.255.255.255')
+ self.assertEqual(t, "::ffff:255.255.255.255")
def test_ntoa14(self):
- b = binascii.unhexlify(b'0000000000000000000000000001ffff')
+ b = binascii.unhexlify(b"0000000000000000000000000001ffff")
t = ntoa6(b)
- self.assertEqual(t, '::0.1.255.255')
+ self.assertEqual(t, "::0.1.255.255")
def test_ntoa15(self):
# This exercises the current_len > best_len branch in the <= case.
- b = binascii.unhexlify(b'0000ffff00000000ffff00000000ffff')
+ b = binascii.unhexlify(b"0000ffff00000000ffff00000000ffff")
t = ntoa6(b)
- self.assertEqual(t, '0:ffff::ffff:0:0:ffff')
+ self.assertEqual(t, "0:ffff::ffff:0:0:ffff")
def test_bad_ntoa1(self):
def bad():
- ntoa6(b'')
+ ntoa6(b"")
+
self.assertRaises(ValueError, bad)
def test_bad_ntoa2(self):
def bad():
- ntoa6(b'\x00' * 17)
+ ntoa6(b"\x00" * 17)
+
self.assertRaises(ValueError, bad)
def test_bad_ntoa3(self):
def bad():
- ntoa4(b'\x00' * 5)
+ ntoa4(b"\x00" * 5)
+
# Ideally we'd have been consistent and raised ValueError as
# we do for IPv6, but oh well!
self.assertRaises(dns.exception.SyntaxError, bad)
def test_good_v4_aton(self):
- pairs = [('1.2.3.4', b'\x01\x02\x03\x04'),
- ('255.255.255.255', b'\xff\xff\xff\xff'),
- ('0.0.0.0', b'\x00\x00\x00\x00')]
+ pairs = [
+ ("1.2.3.4", b"\x01\x02\x03\x04"),
+ ("255.255.255.255", b"\xff\xff\xff\xff"),
+ ("0.0.0.0", b"\x00\x00\x00\x00"),
+ ]
for (t, b) in pairs:
b1 = aton4(t)
t1 = ntoa4(b1)
def make_bad(a):
def bad():
return aton4(a)
+
return bad
+
for addr in v4_bad_addrs:
self.assertRaises(dns.exception.SyntaxError, make_bad(addr))
def test_bad_v6_aton(self):
- addrs = ['+::0', '0::0::', '::0::', '1:2:3:4:5:6:7:8:9',
- ':::::::']
- embedded = ['::' + x for x in v4_bad_addrs]
+ addrs = ["+::0", "0::0::", "::0::", "1:2:3:4:5:6:7:8:9", ":::::::"]
+ embedded = ["::" + x for x in v4_bad_addrs]
addrs.extend(embedded)
+
def make_bad(a):
def bad():
x = aton6(a)
+
return bad
+
for addr in addrs:
self.assertRaises(dns.exception.SyntaxError, make_bad(addr))
def test_rfc5952_section_4_2_2(self):
- addr = '2001:db8:0:1:1:1:1:1'
+ addr = "2001:db8:0:1:1:1:1:1"
b1 = aton6(addr)
t1 = ntoa6(b1)
self.assertEqual(t1, addr)
def test_is_mapped(self):
- t1 = '2001:db8:0:1:1:1:1:1'
- t2 = '::ffff:127.0.0.1'
- t3 = '1::ffff:127.0.0.1'
+ t1 = "2001:db8:0:1:1:1:1:1"
+ t2 = "::ffff:127.0.0.1"
+ t3 = "1::ffff:127.0.0.1"
self.assertFalse(dns.ipv6.is_mapped(aton6(t1)))
self.assertTrue(dns.ipv6.is_mapped(aton6(t2)))
self.assertFalse(dns.ipv6.is_mapped(aton6(t3)))
def test_is_multicast(self):
- t1 = '223.0.0.1'
- t2 = '240.0.0.1'
- t3 = '224.0.0.1'
- t4 = '239.0.0.1'
- t5 = 'fe00::1'
- t6 = 'ff00::1'
+ t1 = "223.0.0.1"
+ t2 = "240.0.0.1"
+ t3 = "224.0.0.1"
+ t4 = "239.0.0.1"
+ t5 = "fe00::1"
+ t6 = "ff00::1"
self.assertFalse(dns.inet.is_multicast(t1))
self.assertFalse(dns.inet.is_multicast(t2))
self.assertTrue(dns.inet.is_multicast(t3))
def test_is_multicast_bad_input(self):
def bad():
- dns.inet.is_multicast('hello world')
+ dns.inet.is_multicast("hello world")
+
self.assertRaises(ValueError, bad)
def test_ignore_scope(self):
- t1 = 'fe80::1%lo0'
- t2 = 'fe80::1'
+ t1 = "fe80::1%lo0"
+ t2 = "fe80::1"
self.assertEqual(aton6(t1, True), aton6(t2))
def test_do_not_ignore_scope(self):
def bad():
- t1 = 'fe80::1%lo0'
+ t1 = "fe80::1%lo0"
aton6(t1)
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_multiple_scopes_bad(self):
def bad():
- t1 = 'fe80::1%lo0%lo1'
+ t1 = "fe80::1%lo0%lo1"
aton6(t1, True)
+
self.assertRaises(dns.exception.SyntaxError, bad)
def test_ptontop(self):
- for (af, a) in [(socket.AF_INET, '1.2.3.4'),
- (socket.AF_INET6, '2001:db8:0:1:1:1:1:1')]:
- self.assertEqual(dns.inet.inet_ntop(af, dns.inet.inet_pton(af, a)),
- a)
+ for (af, a) in [
+ (socket.AF_INET, "1.2.3.4"),
+ (socket.AF_INET6, "2001:db8:0:1:1:1:1:1"),
+ ]:
+ self.assertEqual(dns.inet.inet_ntop(af, dns.inet.inet_pton(af, a)), a)
def test_isaddress(self):
- for (t, e) in [('1.2.3.4', True),
- ('2001:db8:0:1:1:1:1:1', True),
- ('hello world', False),
- ('http://www.dnspython.org', False),
- ('1.2.3.4a', False),
- ('2001:db8:0:1:1:1:1:q1', False)]:
+ for (t, e) in [
+ ("1.2.3.4", True),
+ ("2001:db8:0:1:1:1:1:1", True),
+ ("hello world", False),
+ ("http://www.dnspython.org", False),
+ ("1.2.3.4a", False),
+ ("2001:db8:0:1:1:1:1:q1", False),
+ ]:
self.assertEqual(dns.inet.is_address(t), e)
def test_low_level_address_tuple(self):
- t = dns.inet.low_level_address_tuple(('1.2.3.4', 53))
- self.assertEqual(t, ('1.2.3.4', 53))
- t = dns.inet.low_level_address_tuple(('2600::1', 53))
- self.assertEqual(t, ('2600::1', 53, 0, 0))
- t = dns.inet.low_level_address_tuple(('1.2.3.4', 53), socket.AF_INET)
- self.assertEqual(t, ('1.2.3.4', 53))
- t = dns.inet.low_level_address_tuple(('2600::1', 53), socket.AF_INET6)
- self.assertEqual(t, ('2600::1', 53, 0, 0))
- t = dns.inet.low_level_address_tuple(('fd80::1%2', 53), socket.AF_INET6)
- self.assertEqual(t, ('fd80::1', 53, 0, 2))
+ t = dns.inet.low_level_address_tuple(("1.2.3.4", 53))
+ self.assertEqual(t, ("1.2.3.4", 53))
+ t = dns.inet.low_level_address_tuple(("2600::1", 53))
+ self.assertEqual(t, ("2600::1", 53, 0, 0))
+ t = dns.inet.low_level_address_tuple(("1.2.3.4", 53), socket.AF_INET)
+ self.assertEqual(t, ("1.2.3.4", 53))
+ t = dns.inet.low_level_address_tuple(("2600::1", 53), socket.AF_INET6)
+ self.assertEqual(t, ("2600::1", 53, 0, 0))
+ t = dns.inet.low_level_address_tuple(("fd80::1%2", 53), socket.AF_INET6)
+ self.assertEqual(t, ("fd80::1", 53, 0, 2))
try:
# This can fail on windows for python < 3.8, so we tolerate
# the failure and only test if we have something we can work
pair = p
break
if pair:
- address = 'fd80::1%' + pair[1]
- t = dns.inet.low_level_address_tuple((address, 53),
- socket.AF_INET6)
- self.assertEqual(t, ('fd80::1', 53, 0, pair[0]))
+ address = "fd80::1%" + pair[1]
+ t = dns.inet.low_level_address_tuple((address, 53), socket.AF_INET6)
+ self.assertEqual(t, ("fd80::1", 53, 0, pair[0]))
+
def bad():
bogus = socket.AF_INET + socket.AF_INET6 + 1
- t = dns.inet.low_level_address_tuple(('2600::1', 53), bogus)
+ t = dns.inet.low_level_address_tuple(("2600::1", 53), bogus)
+
self.assertRaises(NotImplementedError, bad)
def test_bogus_family(self):
- self.assertRaises(NotImplementedError,
- lambda: dns.inet.inet_pton(12345, 'bogus'))
- self.assertRaises(NotImplementedError,
- lambda: dns.inet.inet_ntop(12345, b'bogus'))
+ self.assertRaises(
+ NotImplementedError, lambda: dns.inet.inet_pton(12345, "bogus")
+ )
+ self.assertRaises(
+ NotImplementedError, lambda: dns.inet.inet_ntop(12345, b"bogus")
+ )
+
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
-
import dns.rdata
import dns.rdataset
import dns.rdtypes.IN.SRV
def test_processing_order_shuffle():
- rds = dns.rdataset.from_text('in', 'a', 300,
- '10.0.0.1', '10.0.0.2', '10.0.0.3')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2", "10.0.0.3")
seen = set()
for i in range(100):
po = rds.processing_order()
def test_processing_order_priority_mx():
- rds = dns.rdataset.from_text('in', 'mx', 300,
- '10 a', '20 b', '20 c')
+ rds = dns.rdataset.from_text("in", "mx", 300, "10 a", "20 b", "20 c")
seen = set()
for i in range(100):
po = rds.processing_order()
def test_processing_order_priority_weighted():
- rds = dns.rdataset.from_text('in', 'srv', 300,
- '1 10 1234 a', '2 90 1234 b', '2 10 1234 c')
+ rds = dns.rdataset.from_text(
+ "in", "srv", 300, "1 10 1234 a", "2 90 1234 b", "2 10 1234 c"
+ )
seen = set()
weight_90_count = 0
weight_10_count = 0
def test_processing_order_priority_naptr():
- rds = dns.rdataset.from_text('in', 'naptr', 300,
- '1 10 a b c foo.', '1 20 a b c foo.',
- '2 10 a b c foo.', '2 10 d e f bar.')
+ rds = dns.rdataset.from_text(
+ "in",
+ "naptr",
+ 300,
+ "1 10 a b c foo.",
+ "1 20 a b c foo.",
+ "2 10 a b c foo.",
+ "2 10 d e f bar.",
+ )
seen = set()
for i in range(100):
po = rds.processing_order()
def test_processing_order_empty():
- rds = dns.rdataset.from_text('in', 'naptr', 300)
+ rds = dns.rdataset.from_text("in", "naptr", 300)
po = rds.processing_order()
assert po == []
def test_processing_singleton_priority():
- rds = dns.rdataset.from_text('in', 'mx', 300, '10 a')
+ rds = dns.rdataset.from_text("in", "mx", 300, "10 a")
po = rds.processing_order()
assert po == [rds[0]]
def test_processing_singleton_weighted():
- rds = dns.rdataset.from_text('in', 'srv', 300, '1 10 1234 a')
+ rds = dns.rdataset.from_text("in", "srv", 300, "1 10 1234 a")
po = rds.processing_order()
assert po == [rds[0]]
def test_processing_all_zero_weight_srv():
- rds = dns.rdataset.from_text('in', 'srv', 300,
- '1 0 1234 a', '1 0 1234 b', '1 0 1234 c')
+ rds = dns.rdataset.from_text(
+ "in", "srv", 300, "1 0 1234 a", "1 0 1234 b", "1 0 1234 c"
+ )
seen = set()
for i in range(100):
po = rds.processing_order()
# We're testing here just to provide coverage for URI methods; the
# testing of the weighting algorithm is done above in tests with
# SRV.
- rds = dns.rdataset.from_text('in', 'uri', 300,
- '1 1 "ftp://ftp1.example.com/public"',
- '2 2 "ftp://ftp2.example.com/public"',
- '3 3 "ftp://ftp3.example.com/public"')
+ rds = dns.rdataset.from_text(
+ "in",
+ "uri",
+ 300,
+ '1 1 "ftp://ftp1.example.com/public"',
+ '2 2 "ftp://ftp2.example.com/public"',
+ '3 3 "ftp://ftp3.example.com/public"',
+ )
po = rds.processing_order()
assert len(po) == 3
for i in range(3):
# We're testing here just to provide coverage for SVCB methods; the
# testing of the priority algorithm is done above in tests with
# MX and NAPTR.
- rds = dns.rdataset.from_text('in', 'svcb', 300,
- "1 . mandatory=alpn alpn=h2",
- "2 . mandatory=alpn alpn=h2",
- "3 . mandatory=alpn alpn=h2")
+ rds = dns.rdataset.from_text(
+ "in",
+ "svcb",
+ 300,
+ "1 . mandatory=alpn alpn=h2",
+ "2 . mandatory=alpn alpn=h2",
+ "3 . mandatory=alpn alpn=h2",
+ )
po = rds.processing_order()
assert len(po) == 3
for i in range(3):
try:
import ssl
+
have_ssl = True
except Exception:
have_ssl = False
# skip those if it's not there.
_network_available = True
try:
- socket.gethostbyname('dnspython.org')
+ socket.gethostbyname("dnspython.org")
except socket.gaierror:
_network_available = False
# those tests.
try:
from .nanonameserver import Server
+
_nanonameserver_available = True
except ImportError:
_nanonameserver_available = False
+
class Server(object):
pass
+
# Probe for IPv4 and IPv6
query_addresses = []
-for (af, address) in ((socket.AF_INET, '8.8.8.8'),
- (socket.AF_INET6, '2001:4860:4860::8888')):
+for (af, address) in (
+ (socket.AF_INET, "8.8.8.8"),
+ (socket.AF_INET6, "2001:4860:4860::8888"),
+):
try:
with socket.socket(af, socket.SOCK_DGRAM) as s:
# Connecting a UDP socket is supposed to return ENETUNREACH if
except Exception:
pass
-keyring = dns.tsigkeyring.from_text({'name': 'tDz6cfXXGtNivRpQ98hr6A=='})
+keyring = dns.tsigkeyring.from_text({"name": "tDz6cfXXGtNivRpQ98hr6A=="})
+
@unittest.skipIf(not _network_available, "Internet not reachable")
class QueryTests(unittest.TestCase):
-
def testQueryUDP(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.udp(q, address, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryUDPWithSocket(self):
for address in query_addresses:
- with socket.socket(dns.inet.af_for_address(address),
- socket.SOCK_DGRAM) as s:
+ with socket.socket(
+ dns.inet.af_for_address(address), socket.SOCK_DGRAM
+ ) as s:
s.setblocking(0)
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.udp(q, address, sock=s, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryTCP(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.tcp(q, address, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryTCPWithSocket(self):
for address in query_addresses:
- with socket.socket(dns.inet.af_for_address(address),
- socket.SOCK_STREAM) as s:
+ with socket.socket(
+ dns.inet.af_for_address(address), socket.SOCK_STREAM
+ ) as s:
ll = dns.inet.low_level_address_tuple((address, 53))
s.settimeout(2)
s.connect(ll)
s.setblocking(0)
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.tcp(q, None, sock=s, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryTLS(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.tls(q, address, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
@unittest.skipUnless(have_ssl, "No SSL support")
def testQueryTLSWithSocket(self):
for address in query_addresses:
- with socket.socket(dns.inet.af_for_address(address),
- socket.SOCK_STREAM) as base_s:
+ with socket.socket(
+ dns.inet.af_for_address(address), socket.SOCK_STREAM
+ ) as base_s:
ll = dns.inet.low_level_address_tuple((address, 853))
base_s.settimeout(2)
base_s.connect(ll)
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
else:
ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
- with ctx.wrap_socket(base_s, server_hostname='dns.google') as s: # lgtm[py/insecure-protocol]
+ with ctx.wrap_socket(
+ base_s, server_hostname="dns.google"
+ ) as s: # lgtm[py/insecure-protocol]
s.setblocking(0)
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
response = dns.query.tls(q, None, sock=s, timeout=2)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testQueryUDPFallback(self):
for address in query_addresses:
- qname = dns.name.from_text('.')
+ qname = dns.name.from_text(".")
q = dns.message.make_query(qname, dns.rdatatype.DNSKEY)
(_, tcp) = dns.query.udp_with_fallback(q, address, timeout=2)
self.assertTrue(tcp)
tcp_s.settimeout(2)
tcp_s.connect(ll)
tcp_s.setblocking(0)
- qname = dns.name.from_text('.')
+ qname = dns.name.from_text(".")
q = dns.message.make_query(qname, dns.rdatatype.DNSKEY)
- (_, tcp) = dns.query.udp_with_fallback(q, address,
- udp_sock=udp_s,
- tcp_sock=tcp_s,
- timeout=2)
+ (_, tcp) = dns.query.udp_with_fallback(
+ q, address, udp_sock=udp_s, tcp_sock=tcp_s, timeout=2
+ )
self.assertTrue(tcp)
def testQueryUDPFallbackNoFallback(self):
for address in query_addresses:
- qname = dns.name.from_text('dns.google.')
+ qname = dns.name.from_text("dns.google.")
q = dns.message.make_query(qname, dns.rdatatype.A)
(_, tcp) = dns.query.udp_with_fallback(q, address, timeout=2)
self.assertFalse(tcp)
def testUDPReceiveQuery(self):
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as listener:
- listener.bind(('127.0.0.1', 0))
+ listener.bind(("127.0.0.1", 0))
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sender:
- sender.bind(('127.0.0.1', 0))
- q = dns.message.make_query('dns.google', dns.rdatatype.A)
+ sender.bind(("127.0.0.1", 0))
+ q = dns.message.make_query("dns.google", dns.rdatatype.A)
dns.query.send_udp(sender, q, listener.getsockname())
expiration = time.time() + 2
- (q, _, addr) = dns.query.receive_udp(listener,
- expiration=expiration)
+ (q, _, addr) = dns.query.receive_udp(listener, expiration=expiration)
self.assertEqual(addr, sender.getsockname())
# for brevity
_d_and_s = dns.query._destination_and_source
-class DestinationAndSourceTests(unittest.TestCase):
+class DestinationAndSourceTests(unittest.TestCase):
def test_af_inferred_from_where(self):
- (af, d, s) = _d_and_s('1.2.3.4', 53, None, 0)
+ (af, d, s) = _d_and_s("1.2.3.4", 53, None, 0)
self.assertEqual(af, socket.AF_INET)
def test_af_inferred_from_where(self):
- (af, d, s) = _d_and_s('1::2', 53, None, 0)
+ (af, d, s) = _d_and_s("1::2", 53, None, 0)
self.assertEqual(af, socket.AF_INET6)
def test_af_inferred_from_source(self):
- (af, d, s) = _d_and_s('https://example/dns-query', 443,
- '1.2.3.4', 0, False)
+ (af, d, s) = _d_and_s("https://example/dns-query", 443, "1.2.3.4", 0, False)
self.assertEqual(af, socket.AF_INET)
def test_af_mismatch(self):
def bad():
- (af, d, s) = _d_and_s('1::2', 53, '1.2.3.4', 0)
+ (af, d, s) = _d_and_s("1::2", 53, "1.2.3.4", 0)
+
self.assertRaises(ValueError, bad)
def test_source_port_but_no_af_inferred(self):
def bad():
- (af, d, s) = _d_and_s('https://example/dns-query', 443,
- None, 12345, False)
+ (af, d, s) = _d_and_s("https://example/dns-query", 443, None, 12345, False)
+
self.assertRaises(ValueError, bad)
def test_where_must_be_an_address(self):
def bad():
- (af, d, s) = _d_and_s('not a valid address', 53, '1.2.3.4', 0)
+ (af, d, s) = _d_and_s("not a valid address", 53, "1.2.3.4", 0)
+
self.assertRaises(ValueError, bad)
def test_destination_is_none_of_where_url(self):
- (af, d, s) = _d_and_s('https://example/dns-query', 443, None, 0, False)
+ (af, d, s) = _d_and_s("https://example/dns-query", 443, None, 0, False)
self.assertEqual(d, None)
def test_v4_wildcard_source_set(self):
- (af, d, s) = _d_and_s('1.2.3.4', 53, None, 12345)
- self.assertEqual(s, ('0.0.0.0', 12345))
+ (af, d, s) = _d_and_s("1.2.3.4", 53, None, 12345)
+ self.assertEqual(s, ("0.0.0.0", 12345))
def test_v6_wildcard_source_set(self):
- (af, d, s) = _d_and_s('1::2', 53, None, 12345)
- self.assertEqual(s, ('::', 12345, 0, 0))
+ (af, d, s) = _d_and_s("1::2", 53, None, 12345)
+ self.assertEqual(s, ("::", 12345, 0, 0))
class AddressesEqualTestCase(unittest.TestCase):
-
def test_v4(self):
- self.assertTrue(dns.query._addresses_equal(socket.AF_INET,
- ('10.0.0.1', 53),
- ('10.0.0.1', 53)))
- self.assertFalse(dns.query._addresses_equal(socket.AF_INET,
- ('10.0.0.1', 53),
- ('10.0.0.2', 53)))
+ self.assertTrue(
+ dns.query._addresses_equal(
+ socket.AF_INET, ("10.0.0.1", 53), ("10.0.0.1", 53)
+ )
+ )
+ self.assertFalse(
+ dns.query._addresses_equal(
+ socket.AF_INET, ("10.0.0.1", 53), ("10.0.0.2", 53)
+ )
+ )
def test_v6(self):
- self.assertTrue(dns.query._addresses_equal(socket.AF_INET6,
- ('1::1', 53),
- ('0001:0000::1', 53)))
- self.assertFalse(dns.query._addresses_equal(socket.AF_INET6,
- ('::1', 53),
- ('::2', 53)))
+ self.assertTrue(
+ dns.query._addresses_equal(
+ socket.AF_INET6, ("1::1", 53), ("0001:0000::1", 53)
+ )
+ )
+ self.assertFalse(
+ dns.query._addresses_equal(socket.AF_INET6, ("::1", 53), ("::2", 53))
+ )
def test_mixed(self):
- self.assertFalse(dns.query._addresses_equal(socket.AF_INET,
- ('10.0.0.1', 53),
- ('::2', 53)))
+ self.assertFalse(
+ dns.query._addresses_equal(socket.AF_INET, ("10.0.0.1", 53), ("::2", 53))
+ )
-axfr_zone = '''
+axfr_zone = """
$TTL 300
@ SOA ns1 root 1 7200 900 1209600 86400
@ NS ns1
@ NS ns2
ns1 A 10.0.0.1
ns2 A 10.0.0.1
-'''
+"""
-class AXFRNanoNameserver(Server):
+class AXFRNanoNameserver(Server):
def handle(self, request):
self.zone = dns.zone.from_text(axfr_zone, origin=self.origin)
self.origin = self.zone.origin
response.question = []
response.flags |= dns.flags.AA
for (name, rdataset) in self.zone.iterate_rdatasets():
- if rdataset.rdtype == dns.rdatatype.SOA and \
- name == dns.name.empty:
+ if rdataset.rdtype == dns.rdatatype.SOA and name == dns.name.empty:
continue
- rrset = dns.rrset.RRset(name, rdataset.rdclass, rdataset.rdtype,
- rdataset.covers)
+ rrset = dns.rrset.RRset(
+ name, rdataset.rdclass, rdataset.rdtype, rdataset.covers
+ )
rrset.update(rdataset)
response.answer.append(rrset)
items.append(response)
items.append(response)
return items
-ixfr_message = '''id 12345
+
+ixfr_message = """id 12345
opcode QUERY
rcode NOERROR
flags AA
example. 300 IN SOA ns1.example. root.example. 4 7200 900 1209600 86400
added2.example. 300 IN A 10.0.0.5
example. 300 IN SOA ns1.example. root.example. 4 7200 900 1209600 86400
-'''
+"""
-ixfr_trailing_junk = ixfr_message + 'junk.example. 300 IN A 10.0.0.6'
+ixfr_trailing_junk = ixfr_message + "junk.example. 300 IN A 10.0.0.6"
-ixfr_up_to_date_message = '''id 12345
+ixfr_up_to_date_message = """id 12345
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
example. 300 IN SOA ns1.example. root.example. 2 7200 900 1209600 86400
-'''
+"""
-axfr_trailing_junk = '''id 12345
+axfr_trailing_junk = """id 12345
opcode QUERY
rcode NOERROR
flags AA
changed.example. 300 IN A 10.0.0.4
example. 300 IN SOA ns1.example. root.example. 3 7200 900 1209600 86400
junk.example. 300 IN A 10.0.0.6
-'''
+"""
-class IXFRNanoNameserver(Server):
+class IXFRNanoNameserver(Server):
def __init__(self, response_text):
super().__init__()
self.response_text = response_text
except Exception:
pass
+
@unittest.skipIf(not _nanonameserver_available, "nanonameserver required")
class XfrTests(unittest.TestCase):
-
def test_axfr(self):
- expected = dns.zone.from_text(axfr_zone, origin='example')
- with AXFRNanoNameserver(origin='example') as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- port=ns.tcp_address[1])
+ expected = dns.zone.from_text(axfr_zone, origin="example")
+ with AXFRNanoNameserver(origin="example") as ns:
+ xfr = dns.query.xfr(ns.tcp_address[0], "example", port=ns.tcp_address[1])
zone = dns.zone.from_xfr(xfr)
self.assertEqual(zone, expected)
def test_axfr_tsig(self):
- expected = dns.zone.from_text(axfr_zone, origin='example')
- with AXFRNanoNameserver(origin='example', keyring=keyring) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- port=ns.tcp_address[1],
- keyring=keyring, keyname='name')
+ expected = dns.zone.from_text(axfr_zone, origin="example")
+ with AXFRNanoNameserver(origin="example", keyring=keyring) as ns:
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ port=ns.tcp_address[1],
+ keyring=keyring,
+ keyname="name",
+ )
zone = dns.zone.from_xfr(xfr)
self.assertEqual(zone, expected)
def test_axfr_root_tsig(self):
- expected = dns.zone.from_text(axfr_zone, origin='.')
- with AXFRNanoNameserver(origin='.', keyring=keyring) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], '.',
- port=ns.tcp_address[1],
- keyring=keyring, keyname='name')
+ expected = dns.zone.from_text(axfr_zone, origin=".")
+ with AXFRNanoNameserver(origin=".", keyring=keyring) as ns:
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ ".",
+ port=ns.tcp_address[1],
+ keyring=keyring,
+ keyname="name",
+ )
zone = dns.zone.from_xfr(xfr)
self.assertEqual(zone, expected)
def test_axfr_udp(self):
def bad():
- with AXFRNanoNameserver(origin='example') as ns:
- xfr = dns.query.xfr(ns.udp_address[0], 'example',
- port=ns.udp_address[1], use_udp=True)
+ with AXFRNanoNameserver(origin="example") as ns:
+ xfr = dns.query.xfr(
+ ns.udp_address[0], "example", port=ns.udp_address[1], use_udp=True
+ )
l = list(xfr)
+
self.assertRaises(ValueError, bad)
def test_axfr_bad_rcode(self):
def bad():
# We just use Server here as by default it will refuse.
with Server() as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- port=ns.tcp_address[1])
+ xfr = dns.query.xfr(
+ ns.tcp_address[0], "example", port=ns.tcp_address[1]
+ )
l = list(xfr)
+
self.assertRaises(dns.query.TransferError, bad)
def test_axfr_trailing_junk(self):
# we use the IXFR server here as it returns messages
def bad():
with IXFRNanoNameserver(axfr_trailing_junk) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- dns.rdatatype.AXFR,
- port=ns.tcp_address[1])
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ dns.rdatatype.AXFR,
+ port=ns.tcp_address[1],
+ )
l = list(xfr)
+
self.assertRaises(dns.exception.FormError, bad)
def test_ixfr_tcp(self):
with IXFRNanoNameserver(ixfr_message) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- dns.rdatatype.IXFR,
- port=ns.tcp_address[1],
- serial=2,
- relativize=False)
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ dns.rdatatype.IXFR,
+ port=ns.tcp_address[1],
+ serial=2,
+ relativize=False,
+ )
l = list(xfr)
self.assertEqual(len(l), 1)
- expected = dns.message.from_text(ixfr_message,
- one_rr_per_rrset=True)
+ expected = dns.message.from_text(ixfr_message, one_rr_per_rrset=True)
expected.id = l[0].id
self.assertEqual(l[0], expected)
def test_ixfr_udp(self):
with IXFRNanoNameserver(ixfr_message) as ns:
- xfr = dns.query.xfr(ns.udp_address[0], 'example',
- dns.rdatatype.IXFR,
- port=ns.udp_address[1],
- serial=2,
- relativize=False, use_udp=True)
+ xfr = dns.query.xfr(
+ ns.udp_address[0],
+ "example",
+ dns.rdatatype.IXFR,
+ port=ns.udp_address[1],
+ serial=2,
+ relativize=False,
+ use_udp=True,
+ )
l = list(xfr)
self.assertEqual(len(l), 1)
- expected = dns.message.from_text(ixfr_message,
- one_rr_per_rrset=True)
+ expected = dns.message.from_text(ixfr_message, one_rr_per_rrset=True)
expected.id = l[0].id
self.assertEqual(l[0], expected)
def test_ixfr_up_to_date(self):
with IXFRNanoNameserver(ixfr_up_to_date_message) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- dns.rdatatype.IXFR,
- port=ns.tcp_address[1],
- serial=2,
- relativize=False)
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ dns.rdatatype.IXFR,
+ port=ns.tcp_address[1],
+ serial=2,
+ relativize=False,
+ )
l = list(xfr)
self.assertEqual(len(l), 1)
- expected = dns.message.from_text(ixfr_up_to_date_message,
- one_rr_per_rrset=True)
+ expected = dns.message.from_text(
+ ixfr_up_to_date_message, one_rr_per_rrset=True
+ )
expected.id = l[0].id
self.assertEqual(l[0], expected)
def test_ixfr_trailing_junk(self):
def bad():
with IXFRNanoNameserver(ixfr_trailing_junk) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- dns.rdatatype.IXFR,
- port=ns.tcp_address[1],
- serial=2,
- relativize=False)
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ dns.rdatatype.IXFR,
+ port=ns.tcp_address[1],
+ serial=2,
+ relativize=False,
+ )
l = list(xfr)
+
self.assertRaises(dns.exception.FormError, bad)
def test_ixfr_base_serial_mismatch(self):
def bad():
with IXFRNanoNameserver(ixfr_message) as ns:
- xfr = dns.query.xfr(ns.tcp_address[0], 'example',
- dns.rdatatype.IXFR,
- port=ns.tcp_address[1],
- serial=1,
- relativize=False)
+ xfr = dns.query.xfr(
+ ns.tcp_address[0],
+ "example",
+ dns.rdatatype.IXFR,
+ port=ns.tcp_address[1],
+ serial=1,
+ relativize=False,
+ )
l = list(xfr)
+
self.assertRaises(dns.exception.FormError, bad)
-class TSIGNanoNameserver(Server):
+class TSIGNanoNameserver(Server):
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.REFUSED)
response.flags |= dns.flags.RA
try:
- if request.qtype == dns.rdatatype.A and \
- request.qclass == dns.rdataclass.IN:
- rrs = dns.rrset.from_text(request.qname, 300,
- 'IN', 'A', '1.2.3.4')
+ if request.qtype == dns.rdatatype.A and request.qclass == dns.rdataclass.IN:
+ rrs = dns.rrset.from_text(request.qname, 300, "IN", "A", "1.2.3.4")
response.answer.append(rrs)
response.set_rcode(dns.rcode.NOERROR)
response.flags |= dns.flags.AA
pass
return response
+
@unittest.skipIf(not _nanonameserver_available, "nanonameserver required")
class TsigTests(unittest.TestCase):
-
def test_tsig(self):
with TSIGNanoNameserver(keyring=keyring) as ns:
- qname = dns.name.from_text('example.com')
- q = dns.message.make_query(qname, 'A')
- q.use_tsig(keyring=keyring, keyname='name')
- response = dns.query.udp(q, ns.udp_address[0],
- port=ns.udp_address[1])
+ qname = dns.name.from_text("example.com")
+ q = dns.message.make_query(qname, "A")
+ q.use_tsig(keyring=keyring, keyname="name")
+ response = dns.query.udp(q, ns.udp_address[0], port=ns.udp_address[1])
self.assertTrue(response.had_tsig)
- rrs = response.get_rrset(response.answer, qname,
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = response.get_rrset(
+ response.answer, qname, dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
- self.assertTrue('1.2.3.4' in seen)
+ self.assertTrue("1.2.3.4" in seen)
-@unittest.skipIf(sys.platform == 'win32',
- 'low level tests do not work on win32')
-class LowLevelWaitTests(unittest.TestCase):
+@unittest.skipIf(sys.platform == "win32", "low level tests do not work on win32")
+class LowLevelWaitTests(unittest.TestCase):
def test_wait_for(self):
try:
(l, r) = socket.socketpair()
class MiscTests(unittest.TestCase):
def test_matches_destination(self):
- self.assertTrue(dns.query._matches_destination(socket.AF_INET,
- ('10.0.0.1', 1234),
- ('10.0.0.1', 1234),
- True))
- self.assertTrue(dns.query._matches_destination(socket.AF_INET6,
- ('1::2', 1234),
- ('0001::2', 1234),
- True))
- self.assertTrue(dns.query._matches_destination(socket.AF_INET,
- ('10.0.0.1', 1234),
- None,
- True))
- self.assertFalse(dns.query._matches_destination(socket.AF_INET,
- ('10.0.0.1', 1234),
- ('10.0.0.2', 1234),
- True))
- self.assertFalse(dns.query._matches_destination(socket.AF_INET,
- ('10.0.0.1', 1234),
- ('10.0.0.1', 1235),
- True))
+ self.assertTrue(
+ dns.query._matches_destination(
+ socket.AF_INET, ("10.0.0.1", 1234), ("10.0.0.1", 1234), True
+ )
+ )
+ self.assertTrue(
+ dns.query._matches_destination(
+ socket.AF_INET6, ("1::2", 1234), ("0001::2", 1234), True
+ )
+ )
+ self.assertTrue(
+ dns.query._matches_destination(
+ socket.AF_INET, ("10.0.0.1", 1234), None, True
+ )
+ )
+ self.assertFalse(
+ dns.query._matches_destination(
+ socket.AF_INET, ("10.0.0.1", 1234), ("10.0.0.2", 1234), True
+ )
+ )
+ self.assertFalse(
+ dns.query._matches_destination(
+ socket.AF_INET, ("10.0.0.1", 1234), ("10.0.0.1", 1235), True
+ )
+ )
with self.assertRaises(dns.query.UnexpectedSource):
- dns.query._matches_destination(socket.AF_INET,
- ('10.0.0.1', 1234),
- ('10.0.0.1', 1235),
- False)
+ dns.query._matches_destination(
+ socket.AF_INET, ("10.0.0.1", 1234), ("10.0.0.1", 1235), False
+ )
import tests.md_module
from tests.util import here
-class RdataTestCase(unittest.TestCase):
+class RdataTestCase(unittest.TestCase):
def test_str(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- "1.2.3.4")
+ rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4")
self.assertEqual(rdata.address, "1.2.3.4")
def test_unicode(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- u"1.2.3.4")
+ rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4")
self.assertEqual(rdata.address, "1.2.3.4")
def test_module_registration(self):
TTXT = 64001
- dns.rdata.register_type(tests.ttxt_module, TTXT, 'TTXT')
- rdata = dns.rdata.from_text(dns.rdataclass.IN, TTXT, 'hello world')
- self.assertEqual(rdata.strings, (b'hello', b'world'))
- self.assertEqual(dns.rdatatype.to_text(TTXT), 'TTXT')
- self.assertEqual(dns.rdatatype.from_text('TTXT'), TTXT)
+ dns.rdata.register_type(tests.ttxt_module, TTXT, "TTXT")
+ rdata = dns.rdata.from_text(dns.rdataclass.IN, TTXT, "hello world")
+ self.assertEqual(rdata.strings, (b"hello", b"world"))
+ self.assertEqual(dns.rdatatype.to_text(TTXT), "TTXT")
+ self.assertEqual(dns.rdatatype.from_text("TTXT"), TTXT)
def test_module_reregistration(self):
def bad():
TTXTTWO = dns.rdatatype.TXT
- dns.rdata.register_type(tests.ttxt_module, TTXTTWO, 'TTXTTWO')
+ dns.rdata.register_type(tests.ttxt_module, TTXTTWO, "TTXTTWO")
+
self.assertRaises(dns.rdata.RdatatypeExists, bad)
def test_module_registration_singleton(self):
STXT = 64002
- dns.rdata.register_type(tests.stxt_module, STXT, 'STXT',
- is_singleton=True)
- rdata1 = dns.rdata.from_text(dns.rdataclass.IN, STXT, 'hello')
- rdata2 = dns.rdata.from_text(dns.rdataclass.IN, STXT, 'world')
+ dns.rdata.register_type(tests.stxt_module, STXT, "STXT", is_singleton=True)
+ rdata1 = dns.rdata.from_text(dns.rdataclass.IN, STXT, "hello")
+ rdata2 = dns.rdata.from_text(dns.rdataclass.IN, STXT, "world")
rdataset = dns.rdataset.from_rdata(3600, rdata1, rdata2)
self.assertEqual(len(rdataset), 1)
- self.assertEqual(rdataset[0].strings, (b'world',))
+ self.assertEqual(rdataset[0].strings, (b"world",))
def test_replace(self):
a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4")
a2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "2.3.4.5")
self.assertEqual(a1.replace(address="2.3.4.5"), a2)
- mx = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- "10 foo.example")
+ mx = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "10 foo.example")
name = dns.name.from_text("bar.example")
self.assertEqual(mx.replace(preference=20).preference, 20)
self.assertEqual(mx.replace(preference=20).exchange, mx.exchange)
a1.replace(address="bogus")
def test_replace_comment(self):
- a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- "1.2.3.4 ;foo")
+ a1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4 ;foo")
self.assertEqual(a1.rdcomment, "foo")
a2 = a1.replace(rdcomment="bar")
self.assertEqual(a1, a2)
def test_to_generic(self):
a = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "1.2.3.4")
- self.assertEqual(str(a.to_generic()), r'\# 4 01020304')
+ self.assertEqual(str(a.to_generic()), r"\# 4 01020304")
mx = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "10 foo.")
- self.assertEqual(str(mx.to_generic()), r'\# 7 000a03666f6f00')
+ self.assertEqual(str(mx.to_generic()), r"\# 7 000a03666f6f00")
- origin = dns.name.from_text('example')
- ns = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- "foo.example.", relativize_to=origin)
- self.assertEqual(str(ns.to_generic(origin=origin)),
- r'\# 13 03666f6f076578616d706c6500')
+ origin = dns.name.from_text("example")
+ ns = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.NS, "foo.example.", relativize_to=origin
+ )
+ self.assertEqual(
+ str(ns.to_generic(origin=origin)), r"\# 13 03666f6f076578616d706c6500"
+ )
def test_txt_unicode(self):
# TXT records are not defined for Unicode, but if we get
# to_text(), it does NOT convert embedded UTF-8 back to
# Unicode; it's just treated as binary TXT data. Probably
# there should be a TXT-like record with an encoding field.
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT,
- '"foo\u200bbar"')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.TXT, '"foo\u200bbar"'
+ )
self.assertEqual(str(rdata), '"foo\\226\\128\\139bar"')
# We used to encode UTF-8 in UTF-8 because we processed
# escapes in quoted strings immediately. This meant that the
# point, emitting \\195\\162 instead of \\226, and thus
# from_text followed by to_text was not the equal to the
# original input like it ought to be.
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT,
- '"foo\\226\\128\\139bar"')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.TXT, '"foo\\226\\128\\139bar"'
+ )
self.assertEqual(str(rdata), '"foo\\226\\128\\139bar"')
# Our fix for TXT-like records uses a new tokenizer method,
# unescape_to_bytes(), which converts Unicode to UTF-8 only
# once.
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.TXT,
- '"foo\u200b\\123bar"')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.TXT, '"foo\u200b\\123bar"'
+ )
self.assertEqual(str(rdata), '"foo\\226\\128\\139{bar"')
def test_unicode_idna2003_in_rdata(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- "Königsgäßchen")
- self.assertEqual(str(rdata.target), 'xn--knigsgsschen-lcb0w')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.NS, "Königsgäßchen"
+ )
+ self.assertEqual(str(rdata.target), "xn--knigsgsschen-lcb0w")
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def test_unicode_idna2008_in_rdata(self):
- rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- "Königsgäßchen",
- idna_codec=dns.name.IDNA_2008)
- self.assertEqual(str(rdata.target), 'xn--knigsgchen-b4a3dun')
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ dns.rdatatype.NS,
+ "Königsgäßchen",
+ idna_codec=dns.name.IDNA_2008,
+ )
+ self.assertEqual(str(rdata.target), "xn--knigsgchen-b4a3dun")
def test_digestable_downcasing(self):
# Make sure all the types listed in RFC 4034 section 6.2 are
# NSEC3, whose downcasing was removed by RFC 6840 section 5.1
#
cases = [
- ('SOA', 'NAME NAME 1 2 3 4 5'),
- ('AFSDB', '0 NAME'),
- ('CNAME', 'NAME'),
- ('DNAME', 'NAME'),
- ('KX', '10 NAME'),
- ('MX', '10 NAME'),
- ('NS', 'NAME'),
- ('NAPTR', '0 0 a B c NAME'),
- ('PTR', 'NAME'),
- ('PX', '65535 NAME NAME'),
- ('RP', 'NAME NAME'),
- ('RT', '0 NAME'),
- ('SRV', '0 0 0 NAME'),
- ('RRSIG',
- 'A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM=')
+ ("SOA", "NAME NAME 1 2 3 4 5"),
+ ("AFSDB", "0 NAME"),
+ ("CNAME", "NAME"),
+ ("DNAME", "NAME"),
+ ("KX", "10 NAME"),
+ ("MX", "10 NAME"),
+ ("NS", "NAME"),
+ ("NAPTR", "0 0 a B c NAME"),
+ ("PTR", "NAME"),
+ ("PX", "65535 NAME NAME"),
+ ("RP", "NAME NAME"),
+ ("RT", "0 NAME"),
+ ("SRV", "0 0 0 NAME"),
+ ("RRSIG", "A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM="),
]
for rdtype, text in cases:
- upper_origin = dns.name.from_text('EXAMPLE')
- lower_origin = dns.name.from_text('example')
- canonical_text = text.replace('NAME', 'name')
- rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype, text,
- origin=upper_origin, relativize=False)
- canonical_rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype,
- canonical_text,
- origin=lower_origin,
- relativize=False)
+ upper_origin = dns.name.from_text("EXAMPLE")
+ lower_origin = dns.name.from_text("example")
+ canonical_text = text.replace("NAME", "name")
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, rdtype, text, origin=upper_origin, relativize=False
+ )
+ canonical_rdata = dns.rdata.from_text(
+ dns.rdataclass.IN,
+ rdtype,
+ canonical_text,
+ origin=lower_origin,
+ relativize=False,
+ )
digestable_wire = rdata.to_digestable()
f = io.BytesIO()
canonical_rdata.to_wire(f)
# handled properly.
#
cases = [
- ('HIP', '2 200100107B1A74DF365639CC39F1D578 Ym9ndXM= NAME name'),
- ('IPSECKEY', '10 3 2 NAME Ym9ndXM='),
- ('NSEC', 'NAME A'),
+ ("HIP", "2 200100107B1A74DF365639CC39F1D578 Ym9ndXM= NAME name"),
+ ("IPSECKEY", "10 3 2 NAME Ym9ndXM="),
+ ("NSEC", "NAME A"),
]
for rdtype, text in cases:
- origin = dns.name.from_text('example')
- rdata = dns.rdata.from_text(dns.rdataclass.IN, rdtype, text,
- origin=origin, relativize=False)
+ origin = dns.name.from_text("example")
+ rdata = dns.rdata.from_text(
+ dns.rdataclass.IN, rdtype, text, origin=origin, relativize=False
+ )
digestable_wire = rdata.to_digestable(origin)
expected_wire = rdata.to_wire(origin=origin)
self.assertEqual(digestable_wire, expected_wire)
def test_basic_relations(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
self.assertTrue(r1 == r1)
self.assertTrue(r1 != r2)
self.assertTrue(r1 < r2)
self.assertTrue(r2 >= r1)
def test_incompatible_relations(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA,
- '::1')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA, "::1")
for oper in [operator.lt, operator.le, operator.ge, operator.gt]:
self.assertRaises(TypeError, lambda: oper(r1, r2))
self.assertFalse(r1 == r2)
def test_immutability(self):
def bad1():
- r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- r.address = '10.0.0.2'
+ r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ r.address = "10.0.0.2"
+
self.assertRaises(TypeError, bad1)
+
def bad2():
- r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
+ r = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
del r.address
+
self.assertRaises(TypeError, bad2)
def test_pickle(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
p = pickle.dumps(r1)
r2 = pickle.loads(p)
self.assertEqual(r1, r2)
# Pickle something with a longer inheritance chain
- r3 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '10 mail.example.')
+ r3 = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.MX, "10 mail.example."
+ )
p = pickle.dumps(r3)
r4 = pickle.loads(p)
self.assertEqual(r3, r4)
def test_AFSDB_properties(self):
- rd = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AFSDB,
- '0 afsdb.example.')
+ rd = dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.AFSDB, "0 afsdb.example."
+ )
self.assertEqual(rd.preference, rd.subtype)
self.assertEqual(rd.exchange, rd.hostname)
def test_misc_good_LOC_text(self):
# test just degrees
- self.equal_loc('60 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 0 0 N 24 39 0.000 E 10.00m 20m 2000m 20m')
- self.equal_loc('60 0 0 N 24 E 10.00m 20m 2000m 20m',
- '60 0 0 N 24 0 0 E 10.00m 20m 2000m 20m')
+ self.equal_loc(
+ "60 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 0 0 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ )
+ self.equal_loc(
+ "60 0 0 N 24 E 10.00m 20m 2000m 20m",
+ "60 0 0 N 24 0 0 E 10.00m 20m 2000m 20m",
+ )
# test variable length latitude
- self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.51 N 24 39 0.000 E 10.00m 20m 2000m 20m')
- self.equal_loc('60 9 0.500 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.5 N 24 39 0.000 E 10.00m 20m 2000m 20m')
- self.equal_loc('60 9 1.000 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 1 N 24 39 0.000 E 10.00m 20m 2000m 20m')
+ self.equal_loc(
+ "60 9 0.510 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.51 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ )
+ self.equal_loc(
+ "60 9 0.500 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.5 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ )
+ self.equal_loc(
+ "60 9 1.000 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 1 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ )
# test variable length longtitude
- self.equal_loc('60 9 0.000 N 24 39 0.510 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 0.51 E 10.00m 20m 2000m 20m')
- self.equal_loc('60 9 0.000 N 24 39 0.500 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 0.5 E 10.00m 20m 2000m 20m')
- self.equal_loc('60 9 0.000 N 24 39 1.000 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 1 E 10.00m 20m 2000m 20m')
+ self.equal_loc(
+ "60 9 0.000 N 24 39 0.510 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.51 E 10.00m 20m 2000m 20m",
+ )
+ self.equal_loc(
+ "60 9 0.000 N 24 39 0.500 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.5 E 10.00m 20m 2000m 20m",
+ )
+ self.equal_loc(
+ "60 9 0.000 N 24 39 1.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 1 E 10.00m 20m 2000m 20m",
+ )
# test siz, hp, vp defaults
- self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m',
- '60 9 0.51 N 24 39 0.000 E 10.00m 1m 10000m 10m')
- self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 2m',
- '60 9 0.51 N 24 39 0.000 E 10.00m 2m 10000m 10m')
- self.equal_loc('60 9 0.510 N 24 39 0.000 E 10.00m 2m 2000m',
- '60 9 0.51 N 24 39 0.000 E 10.00m 2m 2000m 10m')
+ self.equal_loc(
+ "60 9 0.510 N 24 39 0.000 E 10.00m",
+ "60 9 0.51 N 24 39 0.000 E 10.00m 1m 10000m 10m",
+ )
+ self.equal_loc(
+ "60 9 0.510 N 24 39 0.000 E 10.00m 2m",
+ "60 9 0.51 N 24 39 0.000 E 10.00m 2m 10000m 10m",
+ )
+ self.equal_loc(
+ "60 9 0.510 N 24 39 0.000 E 10.00m 2m 2000m",
+ "60 9 0.51 N 24 39 0.000 E 10.00m 2m 2000m 10m",
+ )
# test siz, hp, vp optional units
- self.equal_loc('60 9 0.510 N 24 39 0.000 E 1m 20m 2000m 20m',
- '60 9 0.51 N 24 39 0.000 E 1 20 2000 20')
+ self.equal_loc(
+ "60 9 0.510 N 24 39 0.000 E 1m 20m 2000m 20m",
+ "60 9 0.51 N 24 39 0.000 E 1 20 2000 20",
+ )
def test_LOC_to_text_SW_hemispheres(self):
# As an extra, we test int->float conversion in the constructor
loc = LOC(dns.rdataclass.IN, dns.rdatatype.LOC, -60, -24, 1)
- text = '60 0 0.000 S 24 0 0.000 W 0.01m'
+ text = "60 0 0.000 S 24 0 0.000 W 0.01m"
self.assertEqual(loc.to_text(), text)
def test_zero_size(self):
# This is to exercise the 0 path in _exponent_of.
- loc = dns.rdata.from_text('in', 'loc', '60 S 24 W 1 0')
+ loc = dns.rdata.from_text("in", "loc", "60 S 24 W 1 0")
self.assertEqual(loc.size, 0.0)
def test_bad_LOC_text(self):
- bad_locs = ['60 9 a.000 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 60.000 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.00a N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.0001 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.000 Z 24 39 0.000 E 10.00m 20m 2000m 20m',
- '91 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m',
- '60 60 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m',
-
- '60 9 0.000 N 24 39 a.000 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 60.000 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 0.00a E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 0.0001 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 39 0.000 Z 10.00m 20m 2000m 20m',
- '60 9 0.000 N 181 39 0.000 E 10.00m 20m 2000m 20m',
- '60 9 0.000 N 24 60 0.000 E 10.00m 20m 2000m 20m',
-
- '60 9 0.000 N 24 39 0.000 E 10.00m 100000000m 2000m 20m',
- '60 9 0.000 N 24 39 0.000 E 10.00m 20m 100000000m 20m',
- '60 9 0.000 N 24 39 0.000 E 10.00m 20m 20m 100000000m',
- ]
+ bad_locs = [
+ "60 9 a.000 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 60.000 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.00a N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.0001 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 Z 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "91 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 60 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 a.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 60.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.00a E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.0001 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.000 Z 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 181 39 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 60 0.000 E 10.00m 20m 2000m 20m",
+ "60 9 0.000 N 24 39 0.000 E 10.00m 100000000m 2000m 20m",
+ "60 9 0.000 N 24 39 0.000 E 10.00m 20m 100000000m 20m",
+ "60 9 0.000 N 24 39 0.000 E 10.00m 20m 20m 100000000m",
+ ]
for loc in bad_locs:
with self.assertRaises(dns.exception.SyntaxError):
dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, loc)
def test_bad_LOC_wire(self):
- bad_locs = [(0, 0, 0, 0x934fd901, 0x80000000, 100),
- (0, 0, 0, 0x6cb026ff, 0x80000000, 100),
- (0, 0, 0, 0x80000000, 0xa69fb201, 100),
- (0, 0, 0, 0x80000000, 0x59604dff, 100),
- (0xa0, 0, 0, 0x80000000, 0x80000000, 100),
- (0x0a, 0, 0, 0x80000000, 0x80000000, 100),
- (0, 0xa0, 0, 0x80000000, 0x80000000, 100),
- (0, 0x0a, 0, 0x80000000, 0x80000000, 100),
- (0, 0, 0xa0, 0x80000000, 0x80000000, 100),
- (0, 0, 0x0a, 0x80000000, 0x80000000, 100),
- ]
+ bad_locs = [
+ (0, 0, 0, 0x934FD901, 0x80000000, 100),
+ (0, 0, 0, 0x6CB026FF, 0x80000000, 100),
+ (0, 0, 0, 0x80000000, 0xA69FB201, 100),
+ (0, 0, 0, 0x80000000, 0x59604DFF, 100),
+ (0xA0, 0, 0, 0x80000000, 0x80000000, 100),
+ (0x0A, 0, 0, 0x80000000, 0x80000000, 100),
+ (0, 0xA0, 0, 0x80000000, 0x80000000, 100),
+ (0, 0x0A, 0, 0x80000000, 0x80000000, 100),
+ (0, 0, 0xA0, 0x80000000, 0x80000000, 100),
+ (0, 0, 0x0A, 0x80000000, 0x80000000, 100),
+ ]
for t in bad_locs:
with self.assertRaises(dns.exception.FormError):
- wire = struct.pack('!BBBBIII', 0, t[0], t[1], t[2],
- t[3], t[4], t[5])
- dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.LOC,
- wire, 0, len(wire))
+ wire = struct.pack("!BBBBIII", 0, t[0], t[1], t[2], t[3], t[4], t[5])
+ dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.LOC, wire, 0, len(wire)
+ )
with self.assertRaises(dns.exception.FormError):
- wire = struct.pack('!BBBBIII', 1, 0, 0, 0, 0, 0, 0)
- dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.LOC,
- wire, 0, len(wire))
+ wire = struct.pack("!BBBBIII", 1, 0, 0, 0, 0, 0, 0)
+ dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.LOC, wire, 0, len(wire)
+ )
def equal_wks(self, a, b):
rda = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.WKS, a)
self.assertEqual(rda, rdb)
def test_misc_good_WKS_text(self):
- self.equal_wks('10.0.0.1 tcp ( http )', '10.0.0.1 6 ( 80 )')
- self.equal_wks('10.0.0.1 udp ( domain )', '10.0.0.1 17 ( 53 )')
+ self.equal_wks("10.0.0.1 tcp ( http )", "10.0.0.1 6 ( 80 )")
+ self.equal_wks("10.0.0.1 udp ( domain )", "10.0.0.1 17 ( 53 )")
def test_misc_bad_WKS_text(self):
try:
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.WKS,
- '10.0.0.1 132 ( domain )')
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.WKS, "10.0.0.1 132 ( domain )"
+ )
self.assertTrue(False) # should not happen
except dns.exception.SyntaxError as e:
self.assertIsInstance(e.__cause__, NotImplementedError)
def test_GPOS_float_converters(self):
- rd = dns.rdata.from_text('in', 'gpos', '49 0 0')
+ rd = dns.rdata.from_text("in", "gpos", "49 0 0")
self.assertEqual(rd.float_latitude, 49.0)
self.assertEqual(rd.float_longitude, 0.0)
self.assertEqual(rd.float_altitude, 0.0)
self.assertEqual(rd.float_altitude, 0.0)
def test_bad_GPOS_text(self):
- bad_gpos = ['"-" "116.8652" "250"',
- '"+" "116.8652" "250"',
- '"" "116.8652" "250"',
- '"." "116.8652" "250"',
- '".a" "116.8652" "250"',
- '"a." "116.8652" "250"',
- '"a.a" "116.8652" "250"',
- # We don't need to test all the bad permutations again
- # but we do want to test that badness is detected
- # in the other strings
- '"0" "a" "250"',
- '"0" "0" "a"',
- # finally test bounds
- '"90.1" "0" "0"',
- '"-90.1" "0" "0"',
- '"0" "180.1" "0"',
- '"0" "-180.1" "0"',
- ]
+ bad_gpos = [
+ '"-" "116.8652" "250"',
+ '"+" "116.8652" "250"',
+ '"" "116.8652" "250"',
+ '"." "116.8652" "250"',
+ '".a" "116.8652" "250"',
+ '"a." "116.8652" "250"',
+ '"a.a" "116.8652" "250"',
+ # We don't need to test all the bad permutations again
+ # but we do want to test that badness is detected
+ # in the other strings
+ '"0" "a" "250"',
+ '"0" "0" "a"',
+ # finally test bounds
+ '"90.1" "0" "0"',
+ '"-90.1" "0" "0"',
+ '"0" "180.1" "0"',
+ '"0" "-180.1" "0"',
+ ]
for gpos in bad_gpos:
with self.assertRaises(dns.exception.SyntaxError):
dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.GPOS, gpos)
def test_bad_GPOS_wire(self):
- bad_gpos = [b'\x01',
- b'\x01\x31\x01',
- b'\x01\x31\x01\x31\x01',
- ]
+ bad_gpos = [
+ b"\x01",
+ b"\x01\x31\x01",
+ b"\x01\x31\x01\x31\x01",
+ ]
for wire in bad_gpos:
- self.assertRaises(dns.exception.FormError,
- lambda: dns.rdata.from_wire(dns.rdataclass.IN,
- dns.rdatatype.GPOS,
- wire, 0, len(wire)))
+ self.assertRaises(
+ dns.exception.FormError,
+ lambda: dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.GPOS, wire, 0, len(wire)
+ ),
+ )
def test_chaos(self):
# avoid red spot on our coverage :)
- r1 = dns.rdata.from_text(dns.rdataclass.CH, dns.rdatatype.A,
- 'chaos. 12345')
+ r1 = dns.rdata.from_text(dns.rdataclass.CH, dns.rdatatype.A, "chaos. 12345")
w = r1.to_wire()
- r2 = dns.rdata.from_wire(dns.rdataclass.CH, dns.rdatatype.A, w, 0,
- len(w))
+ r2 = dns.rdata.from_wire(dns.rdataclass.CH, dns.rdatatype.A, w, 0, len(w))
self.assertEqual(r1, r2)
- self.assertEqual(r1.domain, dns.name.from_text('chaos'))
+ self.assertEqual(r1.domain, dns.name.from_text("chaos"))
# the address input is octal
self.assertEqual(r1.address, 0o12345)
- self.assertEqual(r1.to_text(), 'chaos. 12345')
+ self.assertEqual(r1.to_text(), "chaos. 12345")
def test_opt_repr(self):
opt = OPT(4096, dns.rdatatype.OPT, ())
- self.assertEqual(repr(opt), '<DNS CLASS4096 OPT rdata: >')
+ self.assertEqual(repr(opt), "<DNS CLASS4096 OPT rdata: >")
def test_opt_short_lengths(self):
with self.assertRaises(dns.exception.FormError):
- parser = dns.wire.Parser(bytes.fromhex('f00102'))
+ parser = dns.wire.Parser(bytes.fromhex("f00102"))
OPT.from_wire_parser(4096, dns.rdatatype.OPT, parser)
with self.assertRaises(dns.exception.FormError):
- parser = dns.wire.Parser(bytes.fromhex('f00100030000'))
+ parser = dns.wire.Parser(bytes.fromhex("f00100030000"))
OPT.from_wire_parser(4096, dns.rdatatype.OPT, parser)
def test_from_wire_parser(self):
- wire = bytes.fromhex('01020304')
- rdata = dns.rdata.from_wire('in', 'a', wire, 0, 4)
- self.assertEqual(rdata, dns.rdata.from_text('in', 'a', '1.2.3.4'))
+ wire = bytes.fromhex("01020304")
+ rdata = dns.rdata.from_wire("in", "a", wire, 0, 4)
+ self.assertEqual(rdata, dns.rdata.from_text("in", "a", "1.2.3.4"))
def test_unpickle(self):
- expected_mx = dns.rdata.from_text('in', 'mx', '10 mx.example.')
- with open(here('mx-2-0.pickle'), 'rb') as f:
+ expected_mx = dns.rdata.from_text("in", "mx", "10 mx.example.")
+ with open(here("mx-2-0.pickle"), "rb") as f:
mx = pickle.load(f)
self.assertEqual(mx, expected_mx)
self.assertIsNone(mx.rdcomment)
def test_escaped_newline_in_quoted_string(self):
- rd = dns.rdata.from_text('in', 'txt', '"foo\\\nbar"')
- self.assertEqual(rd.strings, (b'foo\nbar',))
+ rd = dns.rdata.from_text("in", "txt", '"foo\\\nbar"')
+ self.assertEqual(rd.strings, (b"foo\nbar",))
self.assertEqual(rd.to_text(), '"foo\\010bar"')
def test_escaped_newline_in_nonquoted_string(self):
with self.assertRaises(dns.exception.UnexpectedEnd):
- dns.rdata.from_text('in', 'txt', 'foo\\\nbar')
+ dns.rdata.from_text("in", "txt", "foo\\\nbar")
def test_wordbreak(self):
- text = b'abcdefgh'
- self.assertEqual(dns.rdata._wordbreak(text, 4), 'abcd efgh')
- self.assertEqual(dns.rdata._wordbreak(text, 0), 'abcdefgh')
+ text = b"abcdefgh"
+ self.assertEqual(dns.rdata._wordbreak(text, 4), "abcd efgh")
+ self.assertEqual(dns.rdata._wordbreak(text, 0), "abcdefgh")
def test_escapify(self):
- self.assertEqual(dns.rdata._escapify('abc'), 'abc')
- self.assertEqual(dns.rdata._escapify(b'abc'), 'abc')
- self.assertEqual(dns.rdata._escapify(bytearray(b'abc')), 'abc')
+ self.assertEqual(dns.rdata._escapify("abc"), "abc")
+ self.assertEqual(dns.rdata._escapify(b"abc"), "abc")
+ self.assertEqual(dns.rdata._escapify(bytearray(b"abc")), "abc")
self.assertEqual(dns.rdata._escapify(b'ab"c'), 'ab\\"c')
- self.assertEqual(dns.rdata._escapify(b'ab\\c'), 'ab\\\\c')
- self.assertEqual(dns.rdata._escapify(b'ab\x01c'), 'ab\\001c')
+ self.assertEqual(dns.rdata._escapify(b"ab\\c"), "ab\\\\c")
+ self.assertEqual(dns.rdata._escapify(b"ab\x01c"), "ab\\001c")
def test_truncate_bitmap(self):
- self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x01\x00\x00'),
- b'\x00\x01')
- self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x01\x00\x01'),
- b'\x00\x01\x00\x01')
- self.assertEqual(dns.rdata._truncate_bitmap(b'\x00\x00\x00\x00'),
- b'\x00')
+ self.assertEqual(dns.rdata._truncate_bitmap(b"\x00\x01\x00\x00"), b"\x00\x01")
+ self.assertEqual(
+ dns.rdata._truncate_bitmap(b"\x00\x01\x00\x01"), b"\x00\x01\x00\x01"
+ )
+ self.assertEqual(dns.rdata._truncate_bitmap(b"\x00\x00\x00\x00"), b"\x00")
def test_covers_and_extended_rdatatype(self):
- rd = dns.rdata.from_text('in', 'a', '10.0.0.1')
+ rd = dns.rdata.from_text("in", "a", "10.0.0.1")
self.assertEqual(rd.covers(), dns.rdatatype.NONE)
self.assertEqual(rd.extended_rdatatype(), 0x00000001)
- rd = dns.rdata.from_text('in', 'rrsig',
- 'NSEC 1 3 3600 ' +
- '20200101000000 20030101000000 ' +
- '2143 foo Ym9ndXM=')
+ rd = dns.rdata.from_text(
+ "in",
+ "rrsig",
+ "NSEC 1 3 3600 " + "20200101000000 20030101000000 " + "2143 foo Ym9ndXM=",
+ )
self.assertEqual(rd.covers(), dns.rdatatype.NSEC)
- self.assertEqual(rd.extended_rdatatype(), 0x002f002e)
+ self.assertEqual(rd.extended_rdatatype(), 0x002F002E)
def test_uncomparable(self):
- rd = dns.rdata.from_text('in', 'a', '10.0.0.1')
- self.assertFalse(rd == 'a')
- self.assertTrue(rd != 'a')
+ rd = dns.rdata.from_text("in", "a", "10.0.0.1")
+ self.assertFalse(rd == "a")
+ self.assertTrue(rd != "a")
def test_bad_generic(self):
# does not start with \#
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'type45678', '# 7 000a03666f6f00')
+ dns.rdata.from_text("in", "type45678", "# 7 000a03666f6f00")
# wrong length
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'type45678', '\\# 6 000a03666f6f00')
+ dns.rdata.from_text("in", "type45678", "\\# 6 000a03666f6f00")
def test_empty_generic(self):
- dns.rdata.from_text('in', 'type45678', r'\# 0')
+ dns.rdata.from_text("in", "type45678", r"\# 0")
def test_covered_repr(self):
- text = 'NSEC 1 3 3600 20190101000000 20030101000000 ' + \
- '2143 foo Ym9ndXM='
- rd = dns.rdata.from_text('in', 'rrsig', text)
- self.assertEqual(repr(rd), '<DNS IN RRSIG(NSEC) rdata: ' + text + '>')
+ text = "NSEC 1 3 3600 20190101000000 20030101000000 " + "2143 foo Ym9ndXM="
+ rd = dns.rdata.from_text("in", "rrsig", text)
+ self.assertEqual(repr(rd), "<DNS IN RRSIG(NSEC) rdata: " + text + ">")
def test_bad_registration_implementing_known_type_with_wrong_name(self):
# Try to register an implementation at the MG codepoint that isn't
# called "MG"
with self.assertRaises(dns.rdata.RdatatypeExists):
- dns.rdata.register_type(None, dns.rdatatype.MG, 'NOTMG')
+ dns.rdata.register_type(None, dns.rdatatype.MG, "NOTMG")
def test_registration_implementing_known_type_with_right_name(self):
# Try to register an implementation at the MD codepoint
- dns.rdata.register_type(tests.md_module, dns.rdatatype.MD, 'MD')
- rd = dns.rdata.from_text('in', 'md', 'foo.')
- self.assertEqual(rd.target, dns.name.from_text('foo.'))
+ dns.rdata.register_type(tests.md_module, dns.rdatatype.MD, "MD")
+ rd = dns.rdata.from_text("in", "md", "foo.")
+ self.assertEqual(rd.target, dns.name.from_text("foo."))
def test_CERT_with_string_type(self):
- rd = dns.rdata.from_text('in', 'cert', 'SPKI 1 PRIVATEOID Ym9ndXM=')
- self.assertEqual(rd.to_text(), 'SPKI 1 PRIVATEOID Ym9ndXM=')
+ rd = dns.rdata.from_text("in", "cert", "SPKI 1 PRIVATEOID Ym9ndXM=")
+ self.assertEqual(rd.to_text(), "SPKI 1 PRIVATEOID Ym9ndXM=")
def test_CERT_algorithm(self):
- rd = dns.rdata.from_text('in', 'cert', 'SPKI 1 0 Ym9ndXM=')
+ rd = dns.rdata.from_text("in", "cert", "SPKI 1 0 Ym9ndXM=")
self.assertEqual(rd.algorithm, 0)
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'cert', 'SPKI 1 -1 Ym9ndXM=')
+ dns.rdata.from_text("in", "cert", "SPKI 1 -1 Ym9ndXM=")
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'cert', 'SPKI 1 256 Ym9ndXM=')
+ dns.rdata.from_text("in", "cert", "SPKI 1 256 Ym9ndXM=")
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'cert', 'SPKI 1 BOGUS Ym9ndXM=')
+ dns.rdata.from_text("in", "cert", "SPKI 1 BOGUS Ym9ndXM=")
def test_bad_URI_text(self):
# empty target
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'uri', '10 1 ""')
+ dns.rdata.from_text("in", "uri", '10 1 ""')
# no target
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'uri', '10 1')
+ dns.rdata.from_text("in", "uri", "10 1")
def test_bad_URI_wire(self):
- wire = bytes.fromhex('000a0001')
+ wire = bytes.fromhex("000a0001")
with self.assertRaises(dns.exception.FormError):
- dns.rdata.from_wire('in', 'uri', wire, 0, 4)
+ dns.rdata.from_wire("in", "uri", wire, 0, 4)
def test_bad_NSAP_text(self):
# does not start with 0x
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'nsap', '0y4700')
+ dns.rdata.from_text("in", "nsap", "0y4700")
# odd hex string length
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'nsap', '0x470')
+ dns.rdata.from_text("in", "nsap", "0x470")
def test_bad_CAA_text(self):
# tag too long
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'caa',
- '0 ' + 'a' * 256 + ' "ca.example.net"')
+ dns.rdata.from_text("in", "caa", "0 " + "a" * 256 + ' "ca.example.net"')
# tag not alphanumeric
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'caa',
- '0 a-b "ca.example.net"')
+ dns.rdata.from_text("in", "caa", '0 a-b "ca.example.net"')
def test_bad_HIP_text(self):
# hit too long
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'hip',
- '2 ' +
- '00' * 256 +
- ' Ym9ndXM=')
+ dns.rdata.from_text("in", "hip", "2 " + "00" * 256 + " Ym9ndXM=")
def test_bad_sigtime(self):
try:
- dns.rdata.from_text('in', 'rrsig',
- 'NSEC 1 3 3600 ' +
- '202001010000000 20030101000000 ' +
- '2143 foo Ym9ndXM=')
+ dns.rdata.from_text(
+ "in",
+ "rrsig",
+ "NSEC 1 3 3600 "
+ + "202001010000000 20030101000000 "
+ + "2143 foo Ym9ndXM=",
+ )
self.assertTrue(False) # should not happen
except dns.exception.SyntaxError as e:
- self.assertIsInstance(e.__cause__,
- dns.rdtypes.ANY.RRSIG.BadSigTime)
+ self.assertIsInstance(e.__cause__, dns.rdtypes.ANY.RRSIG.BadSigTime)
try:
- dns.rdata.from_text('in', 'rrsig',
- 'NSEC 1 3 3600 ' +
- '20200101000000 2003010100000 ' +
- '2143 foo Ym9ndXM=')
+ dns.rdata.from_text(
+ "in",
+ "rrsig",
+ "NSEC 1 3 3600 "
+ + "20200101000000 2003010100000 "
+ + "2143 foo Ym9ndXM=",
+ )
self.assertTrue(False) # should not happen
except dns.exception.SyntaxError as e:
- self.assertIsInstance(e.__cause__,
- dns.rdtypes.ANY.RRSIG.BadSigTime)
+ self.assertIsInstance(e.__cause__, dns.rdtypes.ANY.RRSIG.BadSigTime)
def test_empty_TXT(self):
# hit too long
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'txt', '')
+ dns.rdata.from_text("in", "txt", "")
def test_too_long_TXT(self):
# hit too long
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'txt', 'a' * 256)
+ dns.rdata.from_text("in", "txt", "a" * 256)
def equal_smimea(self, a, b):
a = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SMIMEA, a)
self.assertEqual(a, b)
def test_good_SMIMEA(self):
- self.equal_smimea('3 0 1 aabbccddeeff', '3 0 01 AABBCCDDEEFF')
+ self.equal_smimea("3 0 1 aabbccddeeff", "3 0 01 AABBCCDDEEFF")
def test_bad_SMIMEA(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SMIMEA, '1 1 1 aGVsbG8gd29ybGQh')
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.SMIMEA, "1 1 1 aGVsbG8gd29ybGQh"
+ )
def test_bad_APLItem_address_length(self):
with self.assertRaises(ValueError):
# 9999 is used in as an "unknown" address family. In the unlikely
# event it is ever defined, we should switch the test to another
# value.
- dns.rdtypes.IN.APL.APLItem(9999, False, b'0xff' * 128, 255)
+ dns.rdtypes.IN.APL.APLItem(9999, False, b"0xff" * 128, 255)
def test_DNSKEY_chunking(self):
inputs = ( # each with chunking as given by dig, unusual chunking, and no chunking
# example 1
(
- '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryq uB78Pyk/NTEoai5bxoipVQQXzHlzyg==',
- '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocK mnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==',
- '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/NTEoai5bxoipVQQXzHlzyg==',
+ "257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryq uB78Pyk/NTEoai5bxoipVQQXzHlzyg==",
+ "257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocK mnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==",
+ "257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iDSFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/NTEoai5bxoipVQQXzHlzyg==",
),
# example 2
(
- '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/ qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGr CHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=',
- '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeq Hy9mvL5qGQTuaG5TSrNqEA R6b/qvxDx6my4JmEmjUPA1JeEI9Y fTUieMr2UZflu7aIbZFLw0vqiYrywCGrC HXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7 xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=',
- '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGrCHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAstbxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6aslO7jXv16Gws=',
+ "257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/ qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGr CHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=",
+ "257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeq Hy9mvL5qGQTuaG5TSrNqEA R6b/qvxDx6my4JmEmjUPA1JeEI9Y fTUieMr2UZflu7aIbZFLw0vqiYrywCGrC HXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7 xXiP3U5Ll 96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAst bxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6as lO7jXv16Gws=",
+ "257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my4JmEmjUPA1JeEI9YfTUieMr2UZflu7aIbZFLw0vqiYrywCGrCHXLalOrEOmrvAxLvq4vHtuTlH7JIszzYBSes8g1vle6KG7xXiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJh6psNSrQs41QvdcXAej+K2Hl1Wd8kPriec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFaW2m7N/Wy4qcFU13roWKDEAstbxH5CHPoBfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lvu9TAiZPc0oysY6aslO7jXv16Gws=",
),
# example 3
(
- '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+ 1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mx t6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLK l3D0L/cD',
- '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5 AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+ TLKl3D0L/cD',
- '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLKl3D0L/cD',
+ "256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+ 1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mx t6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLK l3D0L/cD",
+ "256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5 AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+ TLKl3D0L/cD",
+ "256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5Ofv4akjQGN2zY5AgB/2jmdR/+1PvXFqzKCAGJv4wjABEBNWLLFm7ew1hHMDZEKVL17aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKaxT4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0P+2F+TLKl3D0L/cD",
),
)
output_map = {
32: (
- '257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iD SFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==',
- '257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy 9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my 4JmEmjUPA1JeEI9YfTUieMr2UZflu7aI bZFLw0vqiYrywCGrCHXLalOrEOmrvAxL vq4vHtuTlH7JIszzYBSes8g1vle6KG7x XiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJ h6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFa W2m7N/Wy4qcFU13roWKDEAstbxH5CHPo BfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lv u9TAiZPc0oysY6aslO7jXv16Gws=',
- '256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5O fv4akjQGN2zY5AgB/2jmdR/+1PvXFqzK CAGJv4wjABEBNWLLFm7ew1hHMDZEKVL1 7aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKax T4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0 P+2F+TLKl3D0L/cD',
+ "257 3 13 aCoEWYBBVsP9Fek2oC8yqU8ocKmnS1iD SFZNORnQuHKtJ9Wpyz+kNryquB78Pyk/ NTEoai5bxoipVQQXzHlzyg==",
+ "257 3 8 AwEAAcw5QLr0IjC0wKbGoBPQv4qmeqHy 9mvL5qGQTuaG5TSrNqEAR6b/qvxDx6my 4JmEmjUPA1JeEI9YfTUieMr2UZflu7aI bZFLw0vqiYrywCGrCHXLalOrEOmrvAxL vq4vHtuTlH7JIszzYBSes8g1vle6KG7x XiP3U5Ll96Qiu6bZ31rlMQSPB20xbqJJ h6psNSrQs41QvdcXAej+K2Hl1Wd8kPri ec4AgiBEh8sk5Pp8W9ROLQ7PcbqqttFa W2m7N/Wy4qcFU13roWKDEAstbxH5CHPo BfZSbIwK4KM6BK/uDHpSPIbiOvOCW+lv u9TAiZPc0oysY6aslO7jXv16Gws=",
+ "256 3 8 AwEAAday3UX323uVzQqtOMQ7EHQYfD5O fv4akjQGN2zY5AgB/2jmdR/+1PvXFqzK CAGJv4wjABEBNWLLFm7ew1hHMDZEKVL1 7aml0EBKI6Dsz6Mxt6n7ScvLtHaFRKax T4i2JxiuVhKdQR9XGMiWAPQKrRM5SLG0 P+2F+TLKl3D0L/cD",
),
56: (t[0] for t in inputs),
- 0: (t[0][:12] + t[0][12:].replace(' ', '') for t in inputs)
+ 0: (t[0][:12] + t[0][12:].replace(" ", "") for t in inputs),
}
for chunksize, outputs in output_map.items():
for input, output in zip(inputs, outputs):
for input_variation in input:
- rr = dns.rdata.from_text('IN', 'DNSKEY', input_variation)
+ rr = dns.rdata.from_text("IN", "DNSKEY", input_variation)
new_text = rr.to_text(chunksize=chunksize)
self.assertEqual(output, new_text)
-
+
def test_relative_vs_absolute_compare_unstrict(self):
try:
saved = dns.rdata._allow_relative_comparisons
dns.rdata._allow_relative_comparisons = True
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www.")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www")
self.assertFalse(r1 == r2)
self.assertTrue(r1 != r2)
self.assertFalse(r1 < r2)
try:
saved = dns.rdata._allow_relative_comparisons
dns.rdata._allow_relative_comparisons = False
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www.")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www")
self.assertFalse(r1 == r2)
self.assertTrue(r1 != r2)
+
def bad1():
r1 < r2
+
def bad2():
r1 <= r2
+
def bad3():
r1 > r2
+
def bad4():
r1 >= r2
+
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
dns.rdata._allow_relative_comparisons = saved
def test_absolute_vs_absolute_compare(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx.')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www.")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "xxx.")
self.assertFalse(r1 == r2)
self.assertTrue(r1 != r2)
self.assertTrue(r1 < r2)
try:
saved = dns.rdata._allow_relative_comparisons
dns.rdata._allow_relative_comparisons = True
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "xxx")
self.assertFalse(r1 == r2)
self.assertTrue(r1 != r2)
self.assertTrue(r1 < r2)
try:
saved = dns.rdata._allow_relative_comparisons
dns.rdata._allow_relative_comparisons = False
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx')
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "www")
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "xxx")
self.assertFalse(r1 == r2)
self.assertTrue(r1 != r2)
+
def bad1():
r1 < r2
+
def bad2():
r1 <= r2
+
def bad3():
r1 > r2
+
def bad4():
r1 >= r2
+
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
finally:
dns.rdata._allow_relative_comparisons = saved
-class UtilTestCase(unittest.TestCase):
+class UtilTestCase(unittest.TestCase):
def test_Gateway_bad_type0(self):
with self.assertRaises(SyntaxError):
- dns.rdtypes.util.Gateway(0, 'bad.')
+ dns.rdtypes.util.Gateway(0, "bad.")
def test_Gateway_bad_type3(self):
with self.assertRaises(SyntaxError):
- dns.rdtypes.util.Gateway(3, 'bad.')
+ dns.rdtypes.util.Gateway(3, "bad.")
def test_Gateway_type4(self):
with self.assertRaises(SyntaxError):
def test_Bitmap(self):
b = dns.rdtypes.util.Bitmap
- tok = dns.tokenizer.Tokenizer('A MX')
+ tok = dns.tokenizer.Tokenizer("A MX")
windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
def test_Bitmap_with_duplicate_types(self):
b = dns.rdtypes.util.Bitmap
- tok = dns.tokenizer.Tokenizer('A MX A A MX')
+ tok = dns.tokenizer.Tokenizer("A MX A A MX")
windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
def test_Bitmap_with_out_of_order_types(self):
b = dns.rdtypes.util.Bitmap
- tok = dns.tokenizer.Tokenizer('MX A')
+ tok = dns.tokenizer.Tokenizer("MX A")
windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
def test_Bitmap_zero_padding_works(self):
b = dns.rdtypes.util.Bitmap
- tok = dns.tokenizer.Tokenizer('SRV')
+ tok = dns.tokenizer.Tokenizer("SRV")
windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0)
def test_Bitmap_has_type_0_set(self):
b = dns.rdtypes.util.Bitmap
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('NONE A MX')
+ tok = dns.tokenizer.Tokenizer("NONE A MX")
b.from_text(tok)
def test_Bitmap_empty_window_not_written(self):
b = dns.rdtypes.util.Bitmap
- tok = dns.tokenizer.Tokenizer('URI CAA') # types 256 and 257
+ tok = dns.tokenizer.Tokenizer("URI CAA") # types 256 and 257
windows = b.from_text(tok).windows
ba = bytearray()
- ba.append(0xc0) # bits 0 and 1 in window 1
+ ba.append(0xC0) # bits 0 and 1 in window 1
self.assertEqual(windows, [(1, bytes(ba))])
def test_Bitmap_ok_parse(self):
- parser = dns.wire.Parser(b'\x00\x01\x40')
+ parser = dns.wire.Parser(b"\x00\x01\x40")
b = dns.rdtypes.util.Bitmap([])
windows = b.from_wire_parser(parser).windows
- self.assertEqual(windows, [(0, b'@')])
+ self.assertEqual(windows, [(0, b"@")])
def test_Bitmap_0_length_window_parse(self):
- parser = dns.wire.Parser(b'\x00\x00')
+ parser = dns.wire.Parser(b"\x00\x00")
with self.assertRaises(ValueError):
b = dns.rdtypes.util.Bitmap([])
b.from_wire_parser(parser)
def test_Bitmap_too_long_parse(self):
- parser = dns.wire.Parser(b'\x00\x21' + b'\x01' * 33)
+ parser = dns.wire.Parser(b"\x00\x21" + b"\x01" * 33)
with self.assertRaises(ValueError):
b = dns.rdtypes.util.Bitmap([])
b.from_wire_parser(parser)
def test_compressed_in_generic_is_bad(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- r'\# 4 000aC000')
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, r"\# 4 000aC000")
def test_rdataset_ttl_conversion(self):
- rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds1 = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
self.assertEqual(rds1.ttl, 300)
- rds2 = dns.rdataset.from_text('in', 'a', '5m', '10.0.0.1')
+ rds2 = dns.rdataset.from_text("in", "a", "5m", "10.0.0.1")
self.assertEqual(rds2.ttl, 300)
with self.assertRaises(ValueError):
- dns.rdataset.from_text('in', 'a', 1.6, '10.0.0.1')
+ dns.rdataset.from_text("in", "a", 1.6, "10.0.0.1")
with self.assertRaises(dns.ttl.BadTTL):
- dns.rdataset.from_text('in', 'a', '10.0.0.1', '10.0.0.2')
+ dns.rdataset.from_text("in", "a", "10.0.0.1", "10.0.0.2")
Rdata = dns.rdata.Rdata
class RdataConvertersTestCase(unittest.TestCase):
def test_as_name(self):
- n = dns.name.from_text('hi')
+ n = dns.name.from_text("hi")
self.assertEqual(Rdata._as_name(n), n)
- self.assertEqual(Rdata._as_name('hi'), n)
+ self.assertEqual(Rdata._as_name("hi"), n)
with self.assertRaises(ValueError):
Rdata._as_name(100)
def test_as_uint8(self):
self.assertEqual(Rdata._as_uint8(0), 0)
with self.assertRaises(ValueError):
- Rdata._as_uint8('hi')
+ Rdata._as_uint8("hi")
with self.assertRaises(ValueError):
Rdata._as_uint8(-1)
with self.assertRaises(ValueError):
def test_as_uint16(self):
self.assertEqual(Rdata._as_uint16(0), 0)
with self.assertRaises(ValueError):
- Rdata._as_uint16('hi')
+ Rdata._as_uint16("hi")
with self.assertRaises(ValueError):
Rdata._as_uint16(-1)
with self.assertRaises(ValueError):
def test_as_uint32(self):
self.assertEqual(Rdata._as_uint32(0), 0)
with self.assertRaises(ValueError):
- Rdata._as_uint32('hi')
+ Rdata._as_uint32("hi")
with self.assertRaises(ValueError):
Rdata._as_uint32(-1)
with self.assertRaises(ValueError):
- Rdata._as_uint32(2 ** 32)
+ Rdata._as_uint32(2**32)
def test_as_uint48(self):
self.assertEqual(Rdata._as_uint48(0), 0)
with self.assertRaises(ValueError):
- Rdata._as_uint48('hi')
+ Rdata._as_uint48("hi")
with self.assertRaises(ValueError):
Rdata._as_uint48(-1)
with self.assertRaises(ValueError):
- Rdata._as_uint48(2 ** 48)
+ Rdata._as_uint48(2**48)
def test_as_int(self):
self.assertEqual(Rdata._as_int(0, 0, 10), 0)
with self.assertRaises(ValueError):
- Rdata._as_int('hi', 0, 10)
+ Rdata._as_int("hi", 0, 10)
with self.assertRaises(ValueError):
Rdata._as_int(-1, 0, 10)
with self.assertRaises(ValueError):
self.assertEqual(Rdata._as_bool(True), True)
self.assertEqual(Rdata._as_bool(False), False)
with self.assertRaises(ValueError):
- Rdata._as_bool('hi')
+ Rdata._as_bool("hi")
def test_as_ttl(self):
self.assertEqual(Rdata._as_ttl(300), 300)
- self.assertEqual(Rdata._as_ttl('5m'), 300)
+ self.assertEqual(Rdata._as_ttl("5m"), 300)
self.assertEqual(Rdata._as_ttl(dns.ttl.MAX_TTL), dns.ttl.MAX_TTL)
with self.assertRaises(dns.ttl.BadTTL):
- Rdata._as_ttl('hi')
+ Rdata._as_ttl("hi")
with self.assertRaises(ValueError):
Rdata._as_ttl(1.9)
with self.assertRaises(ValueError):
Rdata._as_ttl(dns.ttl.MAX_TTL + 1)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
import dns.rdataset
import dns.rdatatype
-class RdatasetTestCase(unittest.TestCase):
+class RdatasetTestCase(unittest.TestCase):
def testCodec2003(self):
- r1 = dns.rdataset.from_text_list('in', 'ns', 30,
- ['Königsgäßchen'])
- r2 = dns.rdataset.from_text_list('in', 'ns', 30,
- ['xn--knigsgsschen-lcb0w'])
+ r1 = dns.rdataset.from_text_list("in", "ns", 30, ["Königsgäßchen"])
+ r2 = dns.rdataset.from_text_list("in", "ns", 30, ["xn--knigsgsschen-lcb0w"])
self.assertEqual(r1, r2)
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testCodec2008(self):
- r1 = dns.rdataset.from_text_list('in', 'ns', 30,
- ['Königsgäßchen'],
- idna_codec=dns.name.IDNA_2008)
- r2 = dns.rdataset.from_text_list('in', 'ns', 30,
- ['xn--knigsgchen-b4a3dun'],
- idna_codec=dns.name.IDNA_2008)
+ r1 = dns.rdataset.from_text_list(
+ "in", "ns", 30, ["Königsgäßchen"], idna_codec=dns.name.IDNA_2008
+ )
+ r2 = dns.rdataset.from_text_list(
+ "in", "ns", 30, ["xn--knigsgchen-b4a3dun"], idna_codec=dns.name.IDNA_2008
+ )
self.assertEqual(r1, r2)
def testCopy(self):
- r1 = dns.rdataset.from_text_list('in', 'a', 30,
- ['10.0.0.1', '10.0.0.2'])
+ r1 = dns.rdataset.from_text_list("in", "a", 30, ["10.0.0.1", "10.0.0.2"])
r2 = r1.copy()
self.assertFalse(r1 is r2)
self.assertTrue(r1 == r2)
def testAddIncompatible(self):
rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.A)
- rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA,
- '::1')
+ rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.AAAA, "::1")
rds.add(rd1, 30)
- self.assertRaises(dns.rdataset.IncompatibleTypes,
- lambda: rds.add(rd2, 30))
+ self.assertRaises(dns.rdataset.IncompatibleTypes, lambda: rds.add(rd2, 30))
def testDifferingCovers(self):
- rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG,
- dns.rdatatype.A)
+ rds = dns.rdataset.Rdataset(
+ dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.A
+ )
rd1 = dns.rdata.from_text(
- dns.rdataclass.IN, dns.rdatatype.RRSIG,
- 'A 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=')
+ dns.rdataclass.IN,
+ dns.rdatatype.RRSIG,
+ "A 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=",
+ )
rd2 = dns.rdata.from_text(
- dns.rdataclass.IN, dns.rdatatype.RRSIG,
- 'AAAA 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=')
+ dns.rdataclass.IN,
+ dns.rdatatype.RRSIG,
+ "AAAA 1 3 3600 20200101000000 20030101000000 2143 foo Ym9ndXM=",
+ )
rds.add(rd1, 30)
- self.assertRaises(dns.rdataset.DifferingCovers,
- lambda: rds.add(rd2, 30))
+ self.assertRaises(dns.rdataset.DifferingCovers, lambda: rds.add(rd2, 30))
def testUnionUpdate(self):
- rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
- rds2 = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2')
- rdse = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2')
+ rds1 = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
+ rds2 = dns.rdataset.from_text("in", "a", 30, "10.0.0.2")
+ rdse = dns.rdataset.from_text("in", "a", 30, "10.0.0.1", "10.0.0.2")
rds1.union_update(rds2)
self.assertEqual(rds1, rdse)
def testIntersectionUpdate(self):
- rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
- rds2 = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2')
- rdse = dns.rdataset.from_text('in', 'a', 30, '10.0.0.2')
+ rds1 = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ rds2 = dns.rdataset.from_text("in", "a", 30, "10.0.0.2")
+ rdse = dns.rdataset.from_text("in", "a", 30, "10.0.0.2")
rds1.intersection_update(rds2)
self.assertEqual(rds1, rdse)
def testNoEqualToOther(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
self.assertFalse(rds == 123)
def testEmptyRdataList(self):
- self.assertRaises(ValueError,
- lambda: dns.rdataset.from_rdata_list(300, []))
+ self.assertRaises(ValueError, lambda: dns.rdataset.from_rdata_list(300, []))
def testToTextNoName(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
text = rds.to_text()
- self.assertEqual(text, '300 IN A 10.0.0.1')
+ self.assertEqual(text, "300 IN A 10.0.0.1")
def testToTextOverrideClass(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
text = rds.to_text(override_rdclass=dns.rdataclass.NONE)
- self.assertEqual(text, '300 NONE A 10.0.0.1')
+ self.assertEqual(text, "300 NONE A 10.0.0.1")
def testRepr(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
self.assertEqual(repr(rds), "<DNS IN A rdataset: [<10.0.0.1>]>")
def testTruncatedRepr(self):
- rds = dns.rdataset.from_text('in', 'txt', 300,
- 'a' * 200)
+ rds = dns.rdataset.from_text("in", "txt", 300, "a" * 200)
# * 99 not * 100 below as the " counts as one of the 100 chars
- self.assertEqual(repr(rds),
- '<DNS IN TXT rdataset: [<"' + 'a' * 99 + '...>]>')
+ self.assertEqual(repr(rds), '<DNS IN TXT rdataset: [<"' + "a" * 99 + "...>]>")
def testStr(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
self.assertEqual(str(rds), "300 IN A 10.0.0.1")
def testMultilineToText(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
self.assertEqual(rds.to_text(), "300 IN A 10.0.0.1\n300 IN A 10.0.0.2")
def testCoveredRepr(self):
- rds = dns.rdataset.from_text('in', 'rrsig', 300,
- 'NSEC 1 3 3600 ' +
- '20190101000000 20030101000000 ' +
- '2143 foo Ym9ndXM=')
+ rds = dns.rdataset.from_text(
+ "in",
+ "rrsig",
+ 300,
+ "NSEC 1 3 3600 " + "20190101000000 20030101000000 " + "2143 foo Ym9ndXM=",
+ )
# Using startswith as I don't care about the repr of the rdata,
# just the covers
- self.assertTrue(repr(rds).startswith(
- '<DNS IN RRSIG(NSEC) rdataset:'))
+ self.assertTrue(repr(rds).startswith("<DNS IN RRSIG(NSEC) rdataset:"))
class ImmutableRdatasetTestCase(unittest.TestCase):
-
def test_basic(self):
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
- rd = dns.rdata.from_text('in', 'a', '10.0.0.3')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ rd = dns.rdata.from_text("in", "a", "10.0.0.3")
irds = dns.rdataset.ImmutableRdataset(rds)
with self.assertRaises(TypeError):
irds.update_ttl(100)
irds.clear()
def test_cloning(self):
- rds1 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
+ rds1 = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
rds1 = dns.rdataset.ImmutableRdataset(rds1)
- rds2 = dns.rdataset.from_text('in', 'a', 300, '10.0.0.2', '10.0.0.3')
+ rds2 = dns.rdataset.from_text("in", "a", 300, "10.0.0.2", "10.0.0.3")
rds2 = dns.rdataset.ImmutableRdataset(rds2)
- expected = dns.rdataset.from_text('in', 'a', 300, '10.0.0.2')
+ expected = dns.rdataset.from_text("in", "a", 300, "10.0.0.2")
intersection = rds1.intersection(rds2)
self.assertEqual(intersection, expected)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
import dns.rdataclass
import dns.rdatatype
+
class RdTypeAndClassTestCase(unittest.TestCase):
# Classes
self.assertFalse(dns.rdataclass.is_metaclass(dns.rdataclass.IN))
def test_class_bytext1(self):
- self.assertEqual(dns.rdataclass.from_text('IN'), dns.rdataclass.IN)
+ self.assertEqual(dns.rdataclass.from_text("IN"), dns.rdataclass.IN)
def test_class_bytext2(self):
- self.assertEqual(dns.rdataclass.from_text('CLASS1'), dns.rdataclass.IN)
+ self.assertEqual(dns.rdataclass.from_text("CLASS1"), dns.rdataclass.IN)
def test_class_bytext_bounds1(self):
- self.assertEqual(dns.rdataclass.from_text('CLASS0'), 0)
- self.assertEqual(dns.rdataclass.from_text('CLASS65535'), 65535)
+ self.assertEqual(dns.rdataclass.from_text("CLASS0"), 0)
+ self.assertEqual(dns.rdataclass.from_text("CLASS65535"), 65535)
def test_class_bytext_bounds2(self):
def bad():
- dns.rdataclass.from_text('CLASS65536')
+ dns.rdataclass.from_text("CLASS65536")
+
self.assertRaises(ValueError, bad)
def test_class_bytext_unknown(self):
def bad():
- dns.rdataclass.from_text('XXX')
+ dns.rdataclass.from_text("XXX")
+
self.assertRaises(dns.rdataclass.UnknownRdataclass, bad)
def test_class_totext1(self):
- self.assertEqual(dns.rdataclass.to_text(dns.rdataclass.IN), 'IN')
+ self.assertEqual(dns.rdataclass.to_text(dns.rdataclass.IN), "IN")
def test_class_totext2(self):
- self.assertEqual(dns.rdataclass.to_text(999), 'CLASS999')
+ self.assertEqual(dns.rdataclass.to_text(999), "CLASS999")
def test_class_totext_bounds1(self):
def bad():
dns.rdataclass.to_text(-1)
+
self.assertRaises(ValueError, bad)
def test_class_totext_bounds2(self):
def bad():
dns.rdataclass.to_text(65536)
+
self.assertRaises(ValueError, bad)
# Types
self.assertFalse(dns.rdatatype.is_singleton(dns.rdatatype.A))
def test_type_bytext1(self):
- self.assertEqual(dns.rdatatype.from_text('A'), dns.rdatatype.A)
+ self.assertEqual(dns.rdatatype.from_text("A"), dns.rdatatype.A)
def test_type_bytext2(self):
- self.assertEqual(dns.rdatatype.from_text('TYPE1'), dns.rdatatype.A)
+ self.assertEqual(dns.rdatatype.from_text("TYPE1"), dns.rdatatype.A)
def test_type_bytext_bounds1(self):
- self.assertEqual(dns.rdatatype.from_text('TYPE0'), 0)
- self.assertEqual(dns.rdatatype.from_text('TYPE65535'), 65535)
+ self.assertEqual(dns.rdatatype.from_text("TYPE0"), 0)
+ self.assertEqual(dns.rdatatype.from_text("TYPE65535"), 65535)
def test_type_bytext_bounds2(self):
def bad():
- dns.rdatatype.from_text('TYPE65536')
+ dns.rdatatype.from_text("TYPE65536")
+
self.assertRaises(ValueError, bad)
def test_type_bytext_unknown(self):
def bad():
- dns.rdatatype.from_text('XXX')
+ dns.rdatatype.from_text("XXX")
+
self.assertRaises(dns.rdatatype.UnknownRdatatype, bad)
def test_type_totext1(self):
- self.assertEqual(dns.rdatatype.to_text(dns.rdatatype.A), 'A')
+ self.assertEqual(dns.rdatatype.to_text(dns.rdatatype.A), "A")
def test_type_totext2(self):
- self.assertEqual(dns.rdatatype.to_text(999), 'TYPE999')
+ self.assertEqual(dns.rdatatype.to_text(999), "TYPE999")
def test_type_totext_bounds1(self):
def bad():
dns.rdatatype.to_text(-1)
+
self.assertRaises(ValueError, bad)
def test_type_totext_bounds2(self):
def bad():
dns.rdatatype.to_text(65536)
+
self.assertRaises(ValueError, bad)
def test_type0_totext(self):
- self.assertEqual(dns.rdatatype.to_text(0), 'TYPE0')
+ self.assertEqual(dns.rdatatype.to_text(0), "TYPE0")
+
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
import dns.rrset
import dns.rdtypes.ANY.DNSKEY
-from typing import Set # pylint: disable=unused-import
+from typing import Set # pylint: disable=unused-import
-class RdtypeAnyDnskeyTestCase(unittest.TestCase):
- def testFlagsAll(self): # type: () -> None
- '''Test that all defined flags are recognized.'''
- good_s = {'SEP', 'REVOKE', 'ZONE'}
+class RdtypeAnyDnskeyTestCase(unittest.TestCase):
+ def testFlagsAll(self): # type: () -> None
+ """Test that all defined flags are recognized."""
+ good_s = {"SEP", "REVOKE", "ZONE"}
good_f = 0x181
- self.assertEqual(dns.rdtypes.ANY.DNSKEY.SEP |
- dns.rdtypes.ANY.DNSKEY.REVOKE |
- dns.rdtypes.ANY.DNSKEY.ZONE, good_f)
-
- def testFlagsRRToText(self): # type: () -> None
- '''Test that RR method returns correct flags.'''
- rr = dns.rrset.from_text('foo', 300, 'IN', 'DNSKEY', '257 3 8 KEY=')[0]
- self.assertEqual(dns.rdtypes.ANY.DNSKEY.ZONE |
- dns.rdtypes.ANY.DNSKEY.SEP,
- rr.flags)
-
-
-if __name__ == '__main__':
+ self.assertEqual(
+ dns.rdtypes.ANY.DNSKEY.SEP
+ | dns.rdtypes.ANY.DNSKEY.REVOKE
+ | dns.rdtypes.ANY.DNSKEY.ZONE,
+ good_f,
+ )
+
+ def testFlagsRRToText(self): # type: () -> None
+ """Test that RR method returns correct flags."""
+ rr = dns.rrset.from_text("foo", 300, "IN", "DNSKEY", "257 3 8 KEY=")[0]
+ self.assertEqual(
+ dns.rdtypes.ANY.DNSKEY.ZONE | dns.rdtypes.ANY.DNSKEY.SEP, rr.flags
+ )
+
+
+if __name__ == "__main__":
unittest.main()
class RdtypeAnyEUI48TestCase(unittest.TestCase):
def testInstOk(self):
- '''Valid binary input.'''
- eui = b'\x01\x23\x45\x67\x89\xab'
- inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
- dns.rdatatype.EUI48,
- eui)
+ """Valid binary input."""
+ eui = b"\x01\x23\x45\x67\x89\xab"
+ inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, dns.rdatatype.EUI48, eui)
self.assertEqual(inst.eui, eui)
def testInstLength(self):
- '''Incorrect input length.'''
- eui = b'\x01\x23\x45\x67\x89\xab\xcd'
+ """Incorrect input length."""
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd"
with self.assertRaises(dns.exception.FormError):
- dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
- dns.rdatatype.EUI48,
- eui)
+ dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, dns.rdatatype.EUI48, eui)
def testFromTextOk(self):
- '''Valid text input.'''
- r1 = dns.rrset.from_text('foo', 300, 'IN', 'EUI48',
- '01-23-45-67-89-ab')
- eui = b'\x01\x23\x45\x67\x89\xab'
+ """Valid text input."""
+ r1 = dns.rrset.from_text("foo", 300, "IN", "EUI48", "01-23-45-67-89-ab")
+ eui = b"\x01\x23\x45\x67\x89\xab"
self.assertEqual(r1[0].eui, eui)
def testFromTextLength(self):
- '''Invalid input length.'''
+ """Invalid input length."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI48',
- '00-01-23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI48", "00-01-23-45-67-89-ab")
def testFromTextDelim(self):
- '''Invalid delimiter.'''
+ """Invalid delimiter."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '01_23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI48", "01_23-45-67-89-ab")
def testFromTextExtraDash(self):
- '''Extra dash instead of hex digit.'''
+ """Extra dash instead of hex digit."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '0--23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI48", "0--23-45-67-89-ab")
def testFromTextMultipleTokens(self):
- '''Invalid input divided to multiple tokens.'''
+ """Invalid input divided to multiple tokens."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI48', '01 23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI48", "01 23-45-67-89-ab")
def testFromTextInvalidHex(self):
- '''Invalid hexadecimal input.'''
+ """Invalid hexadecimal input."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI48', 'g0-23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI48", "g0-23-45-67-89-ab")
def testToTextOk(self):
- '''Valid text output.'''
- eui = b'\x01\x23\x45\x67\x89\xab'
- exp_text = '01-23-45-67-89-ab'
- inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
- dns.rdatatype.EUI48,
- eui)
+ """Valid text output."""
+ eui = b"\x01\x23\x45\x67\x89\xab"
+ exp_text = "01-23-45-67-89-ab"
+ inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, dns.rdatatype.EUI48, eui)
text = inst.to_text()
self.assertEqual(exp_text, text)
def testToWire(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89\xab'
- inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
- dns.rdatatype.EUI48,
- eui)
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89\xab"
+ inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, dns.rdatatype.EUI48, eui)
self.assertEqual(inst.to_wire(), eui)
def testFromWireOk(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89\xab'
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89\xab"
pad_len = 100
- wire = b'x' * pad_len + eui + b'y' * pad_len * 2
- inst = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI48,
- wire, pad_len, len(eui))
+ wire = b"x" * pad_len + eui + b"y" * pad_len * 2
+ inst = dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.EUI48, wire, pad_len, len(eui)
+ )
self.assertEqual(inst.eui, eui)
def testFromWireLength(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89'
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89"
pad_len = 100
- wire = b'x' * pad_len + eui + b'y' * pad_len * 2
+ wire = b"x" * pad_len + eui + b"y" * pad_len * 2
with self.assertRaises(dns.exception.FormError):
- dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI48,
- wire, pad_len, len(eui))
+ dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.EUI48, wire, pad_len, len(eui)
+ )
class RdtypeAnyEUI64TestCase(unittest.TestCase):
def testInstOk(self):
- '''Valid binary input.'''
- eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
- inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
- dns.rdatatype.EUI64,
- eui)
+ """Valid binary input."""
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd\xef"
+ inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, dns.rdatatype.EUI64, eui)
self.assertEqual(inst.eui, eui)
def testInstLength(self):
- '''Incorrect input length.'''
- eui = b'\x01\x23\x45\x67\x89\xab'
+ """Incorrect input length."""
+ eui = b"\x01\x23\x45\x67\x89\xab"
with self.assertRaises(dns.exception.FormError):
- dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
- dns.rdatatype.EUI64,
- eui)
+ dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, dns.rdatatype.EUI64, eui)
def testFromTextOk(self):
- '''Valid text input.'''
- r1 = dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- '01-23-45-67-89-ab-cd-ef')
- eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
+ """Valid text input."""
+ r1 = dns.rrset.from_text("foo", 300, "IN", "EUI64", "01-23-45-67-89-ab-cd-ef")
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd\xef"
self.assertEqual(r1[0].eui, eui)
def testFromTextLength(self):
- '''Invalid input length.'''
+ """Invalid input length."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- '01-23-45-67-89-ab')
+ dns.rrset.from_text("foo", 300, "IN", "EUI64", "01-23-45-67-89-ab")
def testFromTextDelim(self):
- '''Invalid delimiter.'''
+ """Invalid delimiter."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- '01_23-45-67-89-ab-cd-ef')
+ dns.rrset.from_text("foo", 300, "IN", "EUI64", "01_23-45-67-89-ab-cd-ef")
def testFromTextExtraDash(self):
- '''Extra dash instead of hex digit.'''
+ """Extra dash instead of hex digit."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- '0--23-45-67-89-ab-cd-ef')
+ dns.rrset.from_text("foo", 300, "IN", "EUI64", "0--23-45-67-89-ab-cd-ef")
def testFromTextMultipleTokens(self):
- '''Invalid input divided to multiple tokens.'''
+ """Invalid input divided to multiple tokens."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- '01 23-45-67-89-ab-cd-ef')
+ dns.rrset.from_text("foo", 300, "IN", "EUI64", "01 23-45-67-89-ab-cd-ef")
def testFromTextInvalidHex(self):
- '''Invalid hexadecimal input.'''
+ """Invalid hexadecimal input."""
with self.assertRaises(dns.exception.SyntaxError):
- dns.rrset.from_text('foo', 300, 'IN', 'EUI64',
- 'g0-23-45-67-89-ab-cd-ef')
+ dns.rrset.from_text("foo", 300, "IN", "EUI64", "g0-23-45-67-89-ab-cd-ef")
def testToTextOk(self):
- '''Valid text output.'''
- eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
- exp_text = '01-23-45-67-89-ab-cd-ef'
- inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
- dns.rdatatype.EUI64,
- eui)
+ """Valid text output."""
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd\xef"
+ exp_text = "01-23-45-67-89-ab-cd-ef"
+ inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, dns.rdatatype.EUI64, eui)
text = inst.to_text()
self.assertEqual(exp_text, text)
def testToWire(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
- inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
- dns.rdatatype.EUI64,
- eui)
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd\xef"
+ inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, dns.rdatatype.EUI64, eui)
self.assertEqual(inst.to_wire(), eui)
def testFromWireOk(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89\xab\xcd\xef"
pad_len = 100
- wire = b'x' * pad_len + eui + b'y' * pad_len * 2
- inst = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI64,
- wire, pad_len, len(eui))
+ wire = b"x" * pad_len + eui + b"y" * pad_len * 2
+ inst = dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.EUI64, wire, pad_len, len(eui)
+ )
self.assertEqual(inst.eui, eui)
def testFromWireLength(self):
- '''Valid wire format.'''
- eui = b'\x01\x23\x45\x67\x89'
+ """Valid wire format."""
+ eui = b"\x01\x23\x45\x67\x89"
pad_len = 100
- wire = b'x' * pad_len + eui + b'y' * pad_len * 2
+ wire = b"x" * pad_len + eui + b"y" * pad_len * 2
with self.assertRaises(dns.exception.FormError):
- dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.EUI64,
- wire, pad_len, len(eui))
+ dns.rdata.from_wire(
+ dns.rdataclass.IN, dns.rdatatype.EUI64, wire, pad_len, len(eui)
+ )
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
import dns.rrset
import dns.rdtypes.ANY.LOC
-class RdtypeAnyLocTestCase(unittest.TestCase):
+class RdtypeAnyLocTestCase(unittest.TestCase):
def testEqual1(self):
- '''Test default values for size, horizontal and vertical precision.'''
- r1 = dns.rrset.from_text('foo', 300, 'IN', 'LOC',
- '49 11 42.400 N 16 36 29.600 E 227.64m')
- r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
- '49 11 42.400 N 16 36 29.600 E 227.64m '
- '1.00m 10000.00m 10.00m')
+ """Test default values for size, horizontal and vertical precision."""
+ r1 = dns.rrset.from_text(
+ "foo", 300, "IN", "LOC", "49 11 42.400 N 16 36 29.600 E 227.64m"
+ )
+ r2 = dns.rrset.from_text(
+ "FOO",
+ 600,
+ "in",
+ "loc",
+ "49 11 42.400 N 16 36 29.600 E 227.64m " "1.00m 10000.00m 10.00m",
+ )
self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2))
def testEqual2(self):
- '''Test default values for size, horizontal and vertical precision.'''
- r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1),
- (16, 36, 29, 600, 1),
- 22764.0) # centimeters
- r2 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1),
- (16, 36, 29, 600, 1),
- 22764.0, # centimeters
- 100.0, 1000000.00, 1000.0) # centimeters
+ """Test default values for size, horizontal and vertical precision."""
+ r1 = dns.rdtypes.ANY.LOC.LOC(
+ 1, 29, (49, 11, 42, 400, 1), (16, 36, 29, 600, 1), 22764.0
+ ) # centimeters
+ r2 = dns.rdtypes.ANY.LOC.LOC(
+ 1,
+ 29,
+ (49, 11, 42, 400, 1),
+ (16, 36, 29, 600, 1),
+ 22764.0, # centimeters
+ 100.0,
+ 1000000.00,
+ 1000.0,
+ ) # centimeters
self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2))
def testEqual3(self):
- '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m.
+ """Test size, horizontal and vertical precision parsers: 100 cm == 1 m.
- Parsers in from_text() and __init__() have to produce equal results.'''
- r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1),
- (16, 36, 29, 600, 1), 22764.0,
- 200.0, 1000.00, 200.0) # centimeters
- r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
- '49 11 42.400 N 16 36 29.600 E 227.64m '
- '2.00m 10.00m 2.00m')[0]
+ Parsers in from_text() and __init__() have to produce equal results."""
+ r1 = dns.rdtypes.ANY.LOC.LOC(
+ 1,
+ 29,
+ (49, 11, 42, 400, 1),
+ (16, 36, 29, 600, 1),
+ 22764.0,
+ 200.0,
+ 1000.00,
+ 200.0,
+ ) # centimeters
+ r2 = dns.rrset.from_text(
+ "FOO",
+ 600,
+ "in",
+ "loc",
+ "49 11 42.400 N 16 36 29.600 E 227.64m " "2.00m 10.00m 2.00m",
+ )[0]
self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2))
def testEqual4(self):
- '''Test size, horizontal and vertical precision parsers without unit.
+ """Test size, horizontal and vertical precision parsers without unit.
Parsers in from_text() and __init__() have produce equal result
- for values with and without trailing "m".'''
- r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400, 1),
- (16, 36, 29, 600, 1), 22764.0,
- 200.0, 1000.00, 200.0) # centimeters
- r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
- '49 11 42.400 N 16 36 29.600 E 227.64 '
- '2 10 2')[0] # meters without explicit unit
+ for values with and without trailing "m"."""
+ r1 = dns.rdtypes.ANY.LOC.LOC(
+ 1,
+ 29,
+ (49, 11, 42, 400, 1),
+ (16, 36, 29, 600, 1),
+ 22764.0,
+ 200.0,
+ 1000.00,
+ 200.0,
+ ) # centimeters
+ r2 = dns.rrset.from_text(
+ "FOO", 600, "in", "loc", "49 11 42.400 N 16 36 29.600 E 227.64 " "2 10 2"
+ )[
+ 0
+ ] # meters without explicit unit
self.assertEqual(r1, r2, '"{}" != "{}"'.format(r1, r2))
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
class RdtypeAnyTKeyTestCase(unittest.TestCase):
- tkey_rdata_text = 'gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY OTHEROTHEROTHEROTHEROTHEROTHEROT'
- tkey_rdata_text_no_other = 'gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY'
+ tkey_rdata_text = "gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY OTHEROTHEROTHEROTHEROTHEROTHEROT"
+ tkey_rdata_text_no_other = (
+ "gss-tsig. 1594203795 1594206664 3 0 KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY"
+ )
def testTextOptionalData(self):
# construct the rdata from text and extract the TKEY
tkey = dns.rdata.from_text(
- RdataClass.ANY, RdataType.TKEY,
- RdtypeAnyTKeyTestCase.tkey_rdata_text, origin='.')
+ RdataClass.ANY,
+ RdataType.TKEY,
+ RdtypeAnyTKeyTestCase.tkey_rdata_text,
+ origin=".",
+ )
self.assertEqual(type(tkey), dns.rdtypes.ANY.TKEY.TKEY)
# go to text and compare
tkey_out_text = tkey.to_text(relativize=False)
- self.assertEqual(tkey_out_text,
- RdtypeAnyTKeyTestCase.tkey_rdata_text)
+ self.assertEqual(tkey_out_text, RdtypeAnyTKeyTestCase.tkey_rdata_text)
def testTextNoOptionalData(self):
# construct the rdata from text and extract the TKEY
tkey = dns.rdata.from_text(
- RdataClass.ANY, RdataType.TKEY,
- RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other, origin='.')
+ RdataClass.ANY,
+ RdataType.TKEY,
+ RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other,
+ origin=".",
+ )
self.assertEqual(type(tkey), dns.rdtypes.ANY.TKEY.TKEY)
# go to text and compare
tkey_out_text = tkey.to_text(relativize=False)
- self.assertEqual(tkey_out_text,
- RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other)
+ self.assertEqual(tkey_out_text, RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other)
def testWireOptionalData(self):
- key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY')
- other = base64.b64decode('OTHEROTHEROTHEROTHEROTHEROTHEROT')
+ key = base64.b64decode("KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY")
+ other = base64.b64decode("OTHEROTHEROTHEROTHEROTHEROTHEROT")
# construct the TKEY and compare the text output
- tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY,
- dns.rdatatype.TKEY,
- dns.name.from_text('gss-tsig.'),
- 1594203795, 1594206664,
- 3, 0, key, other)
- self.assertEqual(tkey.to_text(relativize=False),
- RdtypeAnyTKeyTestCase.tkey_rdata_text)
+ tkey = dns.rdtypes.ANY.TKEY.TKEY(
+ dns.rdataclass.ANY,
+ dns.rdatatype.TKEY,
+ dns.name.from_text("gss-tsig."),
+ 1594203795,
+ 1594206664,
+ 3,
+ 0,
+ key,
+ other,
+ )
+ self.assertEqual(
+ tkey.to_text(relativize=False), RdtypeAnyTKeyTestCase.tkey_rdata_text
+ )
# go to/from wire and compare the text output
wire = tkey.to_wire()
- tkey_out_wire = dns.rdata.from_wire(dns.rdataclass.ANY,
- dns.rdatatype.TKEY,
- wire, 0, len(wire))
- self.assertEqual(tkey_out_wire.to_text(relativize=False),
- RdtypeAnyTKeyTestCase.tkey_rdata_text)
+ tkey_out_wire = dns.rdata.from_wire(
+ dns.rdataclass.ANY, dns.rdatatype.TKEY, wire, 0, len(wire)
+ )
+ self.assertEqual(
+ tkey_out_wire.to_text(relativize=False),
+ RdtypeAnyTKeyTestCase.tkey_rdata_text,
+ )
def testWireNoOptionalData(self):
- key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY')
+ key = base64.b64decode("KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY")
# construct the TKEY with no 'other' data and compare the text output
- tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY,
- dns.rdatatype.TKEY,
- dns.name.from_text('gss-tsig.'),
- 1594203795, 1594206664,
- 3, 0, key)
- self.assertEqual(tkey.to_text(relativize=False),
- RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other)
+ tkey = dns.rdtypes.ANY.TKEY.TKEY(
+ dns.rdataclass.ANY,
+ dns.rdatatype.TKEY,
+ dns.name.from_text("gss-tsig."),
+ 1594203795,
+ 1594206664,
+ 3,
+ 0,
+ key,
+ )
+ self.assertEqual(
+ tkey.to_text(relativize=False),
+ RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other,
+ )
# go to/from wire and compare the text output
wire = tkey.to_wire()
- tkey_out_wire = dns.rdata.from_wire(dns.rdataclass.ANY,
- dns.rdatatype.TKEY,
- wire, 0, len(wire))
- self.assertEqual(tkey_out_wire.to_text(relativize=False),
- RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other)
+ tkey_out_wire = dns.rdata.from_wire(
+ dns.rdataclass.ANY, dns.rdatatype.TKEY, wire, 0, len(wire)
+ )
+ self.assertEqual(
+ tkey_out_wire.to_text(relativize=False),
+ RdtypeAnyTKeyTestCase.tkey_rdata_text_no_other,
+ )
import dns.tsig
import dns.tsigkeyring
-basic_answer = \
- """flags QR
+basic_answer = """flags QR
edns 0
payload 4096
;QUESTION
foo.example. 30 IN A 10.0.0.2
"""
+
class RendererTestCase(unittest.TestCase):
def test_basic(self):
r = dns.renderer.Renderer(flags=dns.flags.QR, max_size=512)
- qname = dns.name.from_text('foo.example')
+ qname = dns.name.from_text("foo.example")
r.add_question(qname, dns.rdatatype.A)
- rds = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2')
+ rds = dns.rdataset.from_text("in", "a", 30, "10.0.0.1", "10.0.0.2")
r.add_rdataset(dns.renderer.ANSWER, qname, rds)
r.add_edns(0, 0, 4096)
r.write_header()
def test_tsig(self):
r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512)
- qname = dns.name.from_text('foo.example')
+ qname = dns.name.from_text("foo.example")
r.add_question(qname, dns.rdatatype.A)
- keyring = dns.tsigkeyring.from_text({'key' : '12345678'})
+ keyring = dns.tsigkeyring.from_text({"key": "12345678"})
keyname = next(iter(keyring))
r.write_header()
- r.add_tsig(keyname, keyring[keyname], 300, r.id, 0, b'', b'',
- dns.tsig.HMAC_SHA256)
+ r.add_tsig(
+ keyname, keyring[keyname], 300, r.id, 0, b"", b"", dns.tsig.HMAC_SHA256
+ )
wire = r.get_wire()
message = dns.message.from_wire(wire, keyring=keyring)
expected = dns.message.make_query(qname, dns.rdatatype.A)
self.assertEqual(message, expected)
def test_multi_tsig(self):
- qname = dns.name.from_text('foo.example')
- keyring = dns.tsigkeyring.from_text({'key' : '12345678'})
+ qname = dns.name.from_text("foo.example")
+ keyring = dns.tsigkeyring.from_text({"key": "12345678"})
keyname = next(iter(keyring))
r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512)
r.add_question(qname, dns.rdatatype.A)
r.write_header()
- ctx = r.add_multi_tsig(None, keyname, keyring[keyname], 300, r.id, 0,
- b'', b'', dns.tsig.HMAC_SHA256)
+ ctx = r.add_multi_tsig(
+ None,
+ keyname,
+ keyring[keyname],
+ 300,
+ r.id,
+ 0,
+ b"",
+ b"",
+ dns.tsig.HMAC_SHA256,
+ )
wire = r.get_wire()
message = dns.message.from_wire(wire, keyring=keyring, multi=True)
expected = dns.message.make_query(qname, dns.rdatatype.A)
r = dns.renderer.Renderer(flags=dns.flags.RD, max_size=512)
r.add_question(qname, dns.rdatatype.A)
r.write_header()
- ctx = r.add_multi_tsig(ctx, keyname, keyring[keyname], 300, r.id, 0,
- b'', b'', dns.tsig.HMAC_SHA256)
+ ctx = r.add_multi_tsig(
+ ctx, keyname, keyring[keyname], 300, r.id, 0, b"", b"", dns.tsig.HMAC_SHA256
+ )
wire = r.get_wire()
- message = dns.message.from_wire(wire, keyring=keyring,
- tsig_ctx=message.tsig_ctx, multi=True)
+ message = dns.message.from_wire(
+ wire, keyring=keyring, tsig_ctx=message.tsig_ctx, multi=True
+ )
expected = dns.message.make_query(qname, dns.rdatatype.A)
expected.id = message.id
self.assertEqual(message, expected)
-
def test_going_backwards_fails(self):
r = dns.renderer.Renderer(flags=dns.flags.QR, max_size=512)
- qname = dns.name.from_text('foo.example')
+ qname = dns.name.from_text("foo.example")
r.add_question(qname, dns.rdatatype.A)
r.add_edns(0, 0, 4096)
- rds = dns.rdataset.from_text('in', 'a', 30, '10.0.0.1', '10.0.0.2')
+ rds = dns.rdataset.from_text("in", "a", 30, "10.0.0.1", "10.0.0.2")
+
def bad():
r.add_rdataset(dns.renderer.ANSWER, qname, rds)
+
self.assertRaises(dns.exception.FormError, bad)
# Test the resolver's Resolution, i.e. the business logic of the resolver.
+
class ResolutionTestCase(unittest.TestCase):
def setUp(self):
self.resolver = dns.resolver.Resolver(configure=False)
- self.resolver.nameservers = ['10.0.0.1', '10.0.0.2']
- self.resolver.domain = dns.name.from_text('example')
- self.qname = dns.name.from_text('www.dnspython.org')
- self.resn = dns.resolver._Resolution(self.resolver, self.qname,
- 'A', 'IN',
- False, True, False)
+ self.resolver.nameservers = ["10.0.0.1", "10.0.0.2"]
+ self.resolver.domain = dns.name.from_text("example")
+ self.qname = dns.name.from_text("www.dnspython.org")
+ self.resn = dns.resolver._Resolution(
+ self.resolver, self.qname, "A", "IN", False, True, False
+ )
def test_next_request_abs(self):
(request, answer) = self.resn.next_request()
self.assertEqual(request.question[0].rdtype, dns.rdatatype.A)
def test_next_request_rel_with_search(self):
- qname = dns.name.from_text('www.dnspython.org', None)
- abs_qname_1 = dns.name.from_text('www.dnspython.org.example')
- self.resn = dns.resolver._Resolution(self.resolver, qname,
- 'A', 'IN',
- False, True, True)
+ qname = dns.name.from_text("www.dnspython.org", None)
+ abs_qname_1 = dns.name.from_text("www.dnspython.org.example")
+ self.resn = dns.resolver._Resolution(
+ self.resolver, qname, "A", "IN", False, True, True
+ )
(request, answer) = self.resn.next_request()
self.assertTrue(answer is None)
self.assertEqual(request.question[0].name, self.qname)
self.assertTrue(answer is None)
self.assertEqual(request.question[0].name, abs_qname_1)
self.assertEqual(request.question[0].rdtype, dns.rdatatype.A)
+
def bad():
(request, answer) = self.resn.next_request()
+
self.assertRaises(dns.resolver.NXDOMAIN, bad)
def test_next_request_rel_without_search(self):
- qname = dns.name.from_text('www.dnspython.org', None)
- abs_qname_1 = dns.name.from_text('www.dnspython.org.example')
- self.resn = dns.resolver._Resolution(self.resolver, qname,
- 'A', 'IN',
- False, True, False)
+ qname = dns.name.from_text("www.dnspython.org", None)
+ abs_qname_1 = dns.name.from_text("www.dnspython.org.example")
+ self.resn = dns.resolver._Resolution(
+ self.resolver, qname, "A", "IN", False, True, False
+ )
(request, answer) = self.resn.next_request()
self.assertTrue(answer is None)
self.assertEqual(request.question[0].name, self.qname)
self.assertEqual(request.question[0].rdtype, dns.rdatatype.A)
+
def bad():
(request, answer) = self.resn.next_request()
+
self.assertRaises(dns.resolver.NXDOMAIN, bad)
def test_next_request_exhaust_causes_nxdomain(self):
def bad():
(request, answer) = self.resn.next_request()
+
(request, answer) = self.resn.next_request()
self.assertRaises(dns.resolver.NXDOMAIN, bad)
def make_address_response(self, q):
r = dns.message.make_response(q)
- rrs = r.get_rrset(r.answer, self.qname, dns.rdataclass.IN,
- dns.rdatatype.A, create=True)
- rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1'), 300)
+ rrs = r.get_rrset(
+ r.answer, self.qname, dns.rdataclass.IN, dns.rdatatype.A, create=True
+ )
+ rrs.add(
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), 300
+ )
return r
def make_negative_response(self, q, nxdomain=False):
r = dns.message.make_response(q)
- rrs = r.get_rrset(r.authority, q.question[0].name, dns.rdataclass.IN,
- dns.rdatatype.SOA, create=True)
- rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
- '. . 1 2 3 4 300'), 300)
+ rrs = r.get_rrset(
+ r.authority,
+ q.question[0].name,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ create=True,
+ )
+ rrs.add(
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.SOA, ". . 1 2 3 4 300"
+ ),
+ 300,
+ )
if nxdomain:
r.set_rcode(dns.rcode.NXDOMAIN)
return r
r = dns.message.make_response(q)
name = self.qname
for i in range(count):
- rrs = r.get_rrset(r.answer, name, dns.rdataclass.IN,
- dns.rdatatype.CNAME, create=True)
- tname = dns.name.from_text(f'target{i}.')
- rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
- str(tname)), 300)
+ rrs = r.get_rrset(
+ r.answer, name, dns.rdataclass.IN, dns.rdatatype.CNAME, create=True
+ )
+ tname = dns.name.from_text(f"target{i}.")
+ rrs.add(
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, str(tname)),
+ 300,
+ )
name = tname
- rrs = r.get_rrset(r.answer, name, dns.rdataclass.IN,
- dns.rdatatype.A, create=True)
- rrs.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1'), 300)
+ rrs = r.get_rrset(
+ r.answer, name, dns.rdataclass.IN, dns.rdatatype.A, create=True
+ )
+ rrs.add(
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), 300
+ )
return r
def test_next_request_cache_hit(self):
self.resolver.cache = dns.resolver.Cache()
q = dns.message.make_query(self.qname, dns.rdatatype.A)
r = self.make_address_response(q)
- cache_answer = dns.resolver.Answer(self.qname, dns.rdatatype.A,
- dns.rdataclass.IN, r)
- self.resolver.cache.put((self.qname, dns.rdatatype.A,
- dns.rdataclass.IN), cache_answer)
+ cache_answer = dns.resolver.Answer(
+ self.qname, dns.rdatatype.A, dns.rdataclass.IN, r
+ )
+ self.resolver.cache.put(
+ (self.qname, dns.rdatatype.A, dns.rdataclass.IN), cache_answer
+ )
(request, answer) = self.resn.next_request()
self.assertTrue(request is None)
self.assertTrue(answer is cache_answer)
# Note we need an SOA so the cache doesn't expire the answer
# immediately, but our negative response code does that.
r = self.make_negative_response(q)
- cache_answer = dns.resolver.Answer(self.qname, dns.rdatatype.A,
- dns.rdataclass.IN, r)
- self.resolver.cache.put((self.qname, dns.rdatatype.A,
- dns.rdataclass.IN), cache_answer)
+ cache_answer = dns.resolver.Answer(
+ self.qname, dns.rdatatype.A, dns.rdataclass.IN, r
+ )
+ self.resolver.cache.put(
+ (self.qname, dns.rdatatype.A, dns.rdataclass.IN), cache_answer
+ )
+
def bad():
(request, answer) = self.resn.next_request()
+
self.assertRaises(dns.resolver.NoAnswer, bad)
# If raise_on_no_answer is False, we should get a cache hit.
- self.resn = dns.resolver._Resolution(self.resolver, self.qname,
- 'A', 'IN',
- False, False, False)
+ self.resn = dns.resolver._Resolution(
+ self.resolver, self.qname, "A", "IN", False, False, False
+ )
(request, answer) = self.resn.next_request()
self.assertTrue(request is None)
self.assertTrue(answer is cache_answer)
def test_next_request_cached_nxdomain_without_search(self):
# use a relative qname
- qname = dns.name.from_text('www.dnspython.org', None)
- self.resn = dns.resolver._Resolution(self.resolver, qname,
- 'A', 'IN',
- False, True, False)
- qname1 = dns.name.from_text('www.dnspython.org.')
+ qname = dns.name.from_text("www.dnspython.org", None)
+ self.resn = dns.resolver._Resolution(
+ self.resolver, qname, "A", "IN", False, True, False
+ )
+ qname1 = dns.name.from_text("www.dnspython.org.")
# Arrange to get NXDOMAIN hits on it.
self.resolver.cache = dns.resolver.Cache()
q1 = dns.message.make_query(qname1, dns.rdatatype.A)
r1 = self.make_negative_response(q1, True)
- cache_answer = dns.resolver.Answer(qname1, dns.rdatatype.ANY,
- dns.rdataclass.IN, r1)
- self.resolver.cache.put((qname1, dns.rdatatype.ANY,
- dns.rdataclass.IN), cache_answer)
+ cache_answer = dns.resolver.Answer(
+ qname1, dns.rdatatype.ANY, dns.rdataclass.IN, r1
+ )
+ self.resolver.cache.put(
+ (qname1, dns.rdatatype.ANY, dns.rdataclass.IN), cache_answer
+ )
try:
(request, answer) = self.resn.next_request()
self.assertTrue(False) # should not happen!
def test_next_request_cached_nxdomain_with_search(self):
# use a relative qname so we have two qnames to try
- qname = dns.name.from_text('www.dnspython.org', None)
+ qname = dns.name.from_text("www.dnspython.org", None)
# also enable search mode or we'll only see www.dnspython.org.
- self.resn = dns.resolver._Resolution(self.resolver, qname,
- 'A', 'IN',
- False, True, True)
- qname1 = dns.name.from_text('www.dnspython.org.example.')
- qname2 = dns.name.from_text('www.dnspython.org.')
+ self.resn = dns.resolver._Resolution(
+ self.resolver, qname, "A", "IN", False, True, True
+ )
+ qname1 = dns.name.from_text("www.dnspython.org.example.")
+ qname2 = dns.name.from_text("www.dnspython.org.")
# Arrange to get NXDOMAIN hits on both of those qnames.
self.resolver.cache = dns.resolver.Cache()
q1 = dns.message.make_query(qname1, dns.rdatatype.A)
r1 = self.make_negative_response(q1, True)
- cache_answer = dns.resolver.Answer(qname1, dns.rdatatype.ANY,
- dns.rdataclass.IN, r1)
- self.resolver.cache.put((qname1, dns.rdatatype.ANY,
- dns.rdataclass.IN), cache_answer)
+ cache_answer = dns.resolver.Answer(
+ qname1, dns.rdatatype.ANY, dns.rdataclass.IN, r1
+ )
+ self.resolver.cache.put(
+ (qname1, dns.rdatatype.ANY, dns.rdataclass.IN), cache_answer
+ )
q2 = dns.message.make_query(qname2, dns.rdatatype.A)
r2 = self.make_negative_response(q2, True)
- cache_answer = dns.resolver.Answer(qname2, dns.rdatatype.ANY,
- dns.rdataclass.IN, r2)
- self.resolver.cache.put((qname2, dns.rdatatype.ANY,
- dns.rdataclass.IN), cache_answer)
+ cache_answer = dns.resolver.Answer(
+ qname2, dns.rdatatype.ANY, dns.rdataclass.IN, r2
+ )
+ self.resolver.cache.put(
+ (qname2, dns.rdatatype.ANY, dns.rdataclass.IN), cache_answer
+ )
try:
(request, answer) = self.resn.next_request()
self.assertTrue(False) # should not happen!
def test_next_request_rotate(self):
self.resolver.rotate = True
- order1 = ['10.0.0.1', '10.0.0.2']
- order2 = ['10.0.0.2', '10.0.0.1']
+ order1 = ["10.0.0.1", "10.0.0.2"]
+ order2 = ["10.0.0.2", "10.0.0.1"]
seen1 = False
seen2 = False
# We're not interested in testing the randomness, but we'd
# both orders at least once. This test can fail even with
# correct code, but it is *extremely* unlikely.
for count in range(0, 50):
- self.resn = dns.resolver._Resolution(self.resolver, self.qname,
- 'A', 'IN',
- False, True, False)
+ self.resn = dns.resolver._Resolution(
+ self.resolver, self.qname, "A", "IN", False, True, False
+ )
self.resn.next_request()
if self.resn.nameservers == order1:
seen1 = True
self.assertTrue(seen1 and seen2)
def test_next_request_TSIG(self):
- self.resolver.keyring = dns.tsigkeyring.from_text({
- 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
- })
+ self.resolver.keyring = dns.tsigkeyring.from_text(
+ {"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="}
+ )
(keyname, secret) = next(iter(self.resolver.keyring.items()))
- self.resolver.keyname = dns.name.from_text('keyname.')
+ self.resolver.keyname = dns.name.from_text("keyname.")
(request, answer) = self.resn.next_request()
self.assertFalse(request is None)
self.assertEqual(request.keyring.name, keyname)
self.resn.nameservers.remove(nameserver)
(nameserver, _, _, _) = self.resn.next_nameserver()
self.resn.nameservers.remove(nameserver)
+
def bad():
(nameserver, _, _, _) = self.resn.next_nameserver()
+
self.assertRaises(dns.resolver.NoNameservers, bad)
def test_query_result_nameserver_removing_exceptions(self):
# add some nameservers so we have enough to remove :)
- self.resolver.nameservers.extend(['10.0.0.3', '10.0.0.4'])
+ self.resolver.nameservers.extend(["10.0.0.3", "10.0.0.4"])
(request, _) = self.resn.next_request()
- exceptions = [dns.exception.FormError(), EOFError(),
- NotImplementedError(), dns.message.Truncated()]
+ exceptions = [
+ dns.exception.FormError(),
+ EOFError(),
+ NotImplementedError(),
+ dns.message.Truncated(),
+ ]
for i in range(4):
(nameserver, _, _, _) = self.resn.next_nameserver()
if i == 3:
(_, _, _, _) = self.resn.next_nameserver()
(answer, done) = self.resn.query_result(r, None)
self.assertFalse(answer is None)
- cache_answer = self.resolver.cache.get((self.qname, dns.rdatatype.A,
- dns.rdataclass.IN))
+ cache_answer = self.resolver.cache.get(
+ (self.qname, dns.rdatatype.A, dns.rdataclass.IN)
+ )
self.assertTrue(answer is cache_answer)
def test_query_result_no_error_no_data(self):
r = self.make_negative_response(q)
(_, _) = self.resn.next_request()
(_, _, _, _) = self.resn.next_nameserver()
+
def bad():
(answer, done) = self.resn.query_result(r, None)
+
self.assertRaises(dns.resolver.NoAnswer, bad)
def test_query_result_nxdomain(self):
(answer, done) = self.resn.query_result(r, None)
self.assertTrue(answer is None)
self.assertTrue(done)
- cache_answer = self.resolver.cache.get((self.qname, dns.rdatatype.ANY,
- dns.rdataclass.IN))
+ cache_answer = self.resolver.cache.get(
+ (self.qname, dns.rdatatype.ANY, dns.rdataclass.IN)
+ )
self.assertTrue(cache_answer.response is r)
def test_query_result_yxdomain(self):
r.set_rcode(dns.rcode.YXDOMAIN)
(_, _) = self.resn.next_request()
(_, _, _, _) = self.resn.next_nameserver()
+
def bad():
(answer, done) = self.resn.query_result(r, None)
+
self.assertRaises(dns.resolver.YXDOMAIN, bad)
def test_query_result_servfail_no_retry(self):
def test_no_metaqueries(self):
def bad1():
- self.resn = dns.resolver._Resolution(self.resolver, self.qname,
- 'ANY', 'IN',
- False, True, False)
+ self.resn = dns.resolver._Resolution(
+ self.resolver, self.qname, "ANY", "IN", False, True, False
+ )
+
def bad2():
- self.resn = dns.resolver._Resolution(self.resolver, self.qname,
- 'A', 'ANY',
- False, True, False)
+ self.resn = dns.resolver._Resolution(
+ self.resolver, self.qname, "A", "ANY", False, True, False
+ )
+
self.assertRaises(dns.resolver.NoMetaqueries, bad1)
self.assertRaises(dns.resolver.NoMetaqueries, bad2)
# skip those if it's not there.
_network_available = True
try:
- socket.gethostbyname('dnspython.org')
+ socket.gethostbyname("dnspython.org")
except socket.gaierror:
_network_available = False
# those tests.
try:
from .nanonameserver import Server
+
_nanonameserver_available = True
except ImportError:
_nanonameserver_available = False
+
class Server(object):
pass
+
# Look for systemd-resolved, as it does dangling CNAME responses incorrectly.
#
# Currently we simply check if the nameserver is 127.0.0.53.
_systemd_resolved_present = False
try:
_resolver = dns.resolver.Resolver()
- if _resolver.nameservers == ['127.0.0.53']:
+ if _resolver.nameservers == ["127.0.0.53"]:
_systemd_resolved_present = True
except Exception:
pass
-resolv_conf = u"""
+resolv_conf = """
/t/t
# comment 1
; comment 2
class BaseResolverTests(unittest.TestCase):
-
def testRead(self):
f = StringIO(resolv_conf)
r = dns.resolver.Resolver(configure=False)
r.read_resolv_conf(f)
- self.assertEqual(r.nameservers, ['10.0.0.1', '10.0.0.2'])
- self.assertEqual(r.domain, dns.name.from_text('foo'))
+ self.assertEqual(r.nameservers, ["10.0.0.1", "10.0.0.2"])
+ self.assertEqual(r.domain, dns.name.from_text("foo"))
def testReadOptions(self):
f = StringIO(resolv_conf_options1)
r = dns.resolver.Resolver(configure=False)
r.read_resolv_conf(f)
- self.assertEqual(r.nameservers, ['10.0.0.1', '10.0.0.2'])
+ self.assertEqual(r.nameservers, ["10.0.0.1", "10.0.0.2"])
self.assertTrue(r.rotate)
self.assertEqual(r.timeout, 1)
self.assertEqual(r.ndots, 2)
f = StringIO(unknown_and_bad_directives)
r = dns.resolver.Resolver(configure=False)
r.read_resolv_conf(f)
- self.assertEqual(r.nameservers, ['10.0.0.1'])
+ self.assertEqual(r.nameservers, ["10.0.0.1"])
def testReadUnknownOption(self):
# The real test here is ignoring the unknown option
f = StringIO(unknown_option)
r = dns.resolver.Resolver(configure=False)
r.read_resolv_conf(f)
- self.assertEqual(r.nameservers, ['10.0.0.1'])
+ self.assertEqual(r.nameservers, ["10.0.0.1"])
def testCacheExpiration(self):
with FakeTime() as fake_time:
message = dns.message.from_text(message_text)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.A,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(
+ name, dns.rdatatype.A, dns.rdataclass.IN, message
+ )
cache = dns.resolver.Cache()
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
fake_time.sleep(2)
- self.assertTrue(cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
def testCacheCleaning(self):
with FakeTime() as fake_time:
message = dns.message.from_text(message_text)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.A,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(
+ name, dns.rdatatype.A, dns.rdataclass.IN, message
+ )
cache = dns.resolver.Cache(cleaning_interval=1.0)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
fake_time.sleep(2)
cache._maybe_clean()
- self.assertTrue(cache.data.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ cache.data.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
def testCacheNonCleaning(self):
with FakeTime() as fake_time:
message = dns.message.from_text(message_text)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.A,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(
+ name, dns.rdatatype.A, dns.rdataclass.IN, message
+ )
# override TTL as we're testing non-cleaning
answer.expiration = fake_time.time() + 100
cache = dns.resolver.Cache(cleaning_interval=1.0)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
fake_time.sleep(1.1)
- self.assertEqual(cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN)), answer)
+ self.assertEqual(
+ cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)), answer
+ )
def testIndexErrorOnEmptyRRsetAccess(self):
def bad():
message = dns.message.from_text(message_text_mx)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.MX,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(
+ name, dns.rdatatype.MX, dns.rdataclass.IN, message
+ )
return answer[0]
+
self.assertRaises(IndexError, bad)
def testIndexErrorOnEmptyRRsetDelete(self):
def bad():
message = dns.message.from_text(message_text_mx)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.MX,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(
+ name, dns.rdatatype.MX, dns.rdataclass.IN, message
+ )
del answer[0]
+
self.assertRaises(IndexError, bad)
def testRRsetDelete(self):
message = dns.message.from_text(message_text)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.A,
- dns.rdataclass.IN, message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, message)
del answer[0]
self.assertEqual(len(answer), 0)
def testLRUReplace(self):
cache = dns.resolver.LRUCache(4)
for i in range(0, 5):
- name = dns.name.from_text('example%d.' % i)
+ name = dns.name.from_text("example%d." % i)
answer = FakeAnswer(time.time() + 1)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
for i in range(0, 5):
- name = dns.name.from_text('example%d.' % i)
+ name = dns.name.from_text("example%d." % i)
if i == 0:
- self.assertTrue(cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
else:
- self.assertTrue(not cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ not cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
def testLRUDoesLRU(self):
cache = dns.resolver.LRUCache(4)
for i in range(0, 4):
- name = dns.name.from_text('example%d.' % i)
+ name = dns.name.from_text("example%d." % i)
answer = FakeAnswer(time.time() + 1)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
- name = dns.name.from_text('example0.')
+ name = dns.name.from_text("example0.")
cache.get((name, dns.rdatatype.A, dns.rdataclass.IN))
# The LRU is now example1.
- name = dns.name.from_text('example4.')
+ name = dns.name.from_text("example4.")
answer = FakeAnswer(time.time() + 1)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
for i in range(0, 5):
- name = dns.name.from_text('example%d.' % i)
+ name = dns.name.from_text("example%d." % i)
if i == 1:
- self.assertTrue(cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
else:
- self.assertTrue(not cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ self.assertTrue(
+ not cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
def testLRUExpiration(self):
with FakeTime() as fake_time:
cache = dns.resolver.LRUCache(4)
for i in range(0, 4):
- name = dns.name.from_text('example%d.' % i)
+ name = dns.name.from_text("example%d." % i)
answer = FakeAnswer(time.time() + 1)
cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
fake_time.sleep(2)
for i in range(0, 4):
- name = dns.name.from_text('example%d.' % i)
- self.assertTrue(cache.get((name, dns.rdatatype.A,
- dns.rdataclass.IN))
- is None)
+ name = dns.name.from_text("example%d." % i)
+ self.assertTrue(
+ cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) is None
+ )
def test_cache_flush(self):
- name1 = dns.name.from_text('name1')
- name2 = dns.name.from_text('name2')
- name3 = dns.name.from_text('name3')
+ name1 = dns.name.from_text("name1")
+ name2 = dns.name.from_text("name2")
+ name3 = dns.name.from_text("name3")
basic_cache = dns.resolver.Cache()
lru_cache = dns.resolver.LRUCache(100)
for cache in [basic_cache, lru_cache]:
return True
cnode = cnode.next
return False
+
cache = dns.resolver.LRUCache(4)
answer1 = FakeAnswer(time.time() + 10)
answer2 = FakeAnswer(time.time() + 10)
- key = (dns.name.from_text('key.'), dns.rdatatype.A, dns.rdataclass.IN)
+ key = (dns.name.from_text("key."), dns.rdatatype.A, dns.rdataclass.IN)
cache.put(key, answer1)
canswer = cache.get(key)
self.assertTrue(canswer is answer1)
def test_cache_stats(self):
caches = [dns.resolver.Cache(), dns.resolver.LRUCache(4)]
- key1 = (dns.name.from_text('key1.'), dns.rdatatype.A, dns.rdataclass.IN)
- key2 = (dns.name.from_text('key2.'), dns.rdatatype.A, dns.rdataclass.IN)
+ key1 = (dns.name.from_text("key1."), dns.rdatatype.A, dns.rdataclass.IN)
+ key2 = (dns.name.from_text("key2."), dns.rdatatype.A, dns.rdataclass.IN)
for cache in caches:
answer1 = FakeAnswer(time.time() + 10)
answer2 = FakeAnswer(10) # expired!
# with an empty answer section. Other than that it doesn't
# apply.
message = dns.message.from_text(dangling_cname_0_message_text)
- name = dns.name.from_text('example.')
- answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN,
- message)
+ name = dns.name.from_text("example.")
+ answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, message)
+
def test_python_internal_truth(answer):
if answer:
return True
else:
return False
+
self.assertFalse(test_python_internal_truth(answer))
for a in answer:
pass
def testSearchListsRelative(self):
res = dns.resolver.Resolver(configure=False)
- res.domain = dns.name.from_text('example')
- res.search = [dns.name.from_text(x) for x in
- ['dnspython.org', 'dnspython.net']]
- qname = dns.name.from_text('www', None)
+ res.domain = dns.name.from_text("example")
+ res.search = [dns.name.from_text(x) for x in ["dnspython.org", "dnspython.net"]]
+ qname = dns.name.from_text("www", None)
qnames = res._get_qnames_to_try(qname, True)
- self.assertEqual(qnames,
- [dns.name.from_text(x) for x in
- ['www.dnspython.org', 'www.dnspython.net', 'www.']])
+ self.assertEqual(
+ qnames,
+ [
+ dns.name.from_text(x)
+ for x in ["www.dnspython.org", "www.dnspython.net", "www."]
+ ],
+ )
qnames = res._get_qnames_to_try(qname, False)
- self.assertEqual(qnames,
- [dns.name.from_text('www.')])
+ self.assertEqual(qnames, [dns.name.from_text("www.")])
qnames = res._get_qnames_to_try(qname, None)
- self.assertEqual(qnames,
- [dns.name.from_text('www.')])
+ self.assertEqual(qnames, [dns.name.from_text("www.")])
#
# Now change search default on resolver to True
#
res.use_search_by_default = True
qnames = res._get_qnames_to_try(qname, None)
- self.assertEqual(qnames,
- [dns.name.from_text(x) for x in
- ['www.dnspython.org', 'www.dnspython.net', 'www.']])
+ self.assertEqual(
+ qnames,
+ [
+ dns.name.from_text(x)
+ for x in ["www.dnspython.org", "www.dnspython.net", "www."]
+ ],
+ )
#
# Now test ndots
#
- qname = dns.name.from_text('a.b', None)
+ qname = dns.name.from_text("a.b", None)
res.ndots = 1
qnames = res._get_qnames_to_try(qname, True)
- self.assertEqual(qnames,
- [dns.name.from_text(x) for x in
- ['a.b', 'a.b.dnspython.org', 'a.b.dnspython.net']])
+ self.assertEqual(
+ qnames,
+ [
+ dns.name.from_text(x)
+ for x in ["a.b", "a.b.dnspython.org", "a.b.dnspython.net"]
+ ],
+ )
res.ndots = 2
qnames = res._get_qnames_to_try(qname, True)
- self.assertEqual(qnames,
- [dns.name.from_text(x) for x in
- ['a.b.dnspython.org', 'a.b.dnspython.net', 'a.b']])
- qname = dns.name.from_text('a.b.c', None)
+ self.assertEqual(
+ qnames,
+ [
+ dns.name.from_text(x)
+ for x in ["a.b.dnspython.org", "a.b.dnspython.net", "a.b"]
+ ],
+ )
+ qname = dns.name.from_text("a.b.c", None)
qnames = res._get_qnames_to_try(qname, True)
- self.assertEqual(qnames,
- [dns.name.from_text(x) for x in
- ['a.b.c', 'a.b.c.dnspython.org',
- 'a.b.c.dnspython.net']])
+ self.assertEqual(
+ qnames,
+ [
+ dns.name.from_text(x)
+ for x in ["a.b.c", "a.b.c.dnspython.org", "a.b.c.dnspython.net"]
+ ],
+ )
def testSearchListsAbsolute(self):
res = dns.resolver.Resolver(configure=False)
- qname = dns.name.from_text('absolute')
+ qname = dns.name.from_text("absolute")
qnames = res._get_qnames_to_try(qname, True)
self.assertEqual(qnames, [qname])
qnames = res._get_qnames_to_try(qname, False)
self.assertEqual(r.flags, flags)
def testUseTSIG(self):
- keyring = dns.tsigkeyring.from_text(
- {
- 'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ=='
- }
- )
+ keyring = dns.tsigkeyring.from_text({"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="})
r = dns.resolver.Resolver(configure=False)
r.use_tsig(keyring)
self.assertEqual(r.keyring, keyring)
self.assertEqual(r.keyname, None)
self.assertEqual(r.keyalgorithm, dns.tsig.default_algorithm)
-keyname = dns.name.from_text('keyname')
+keyname = dns.name.from_text("keyname")
@unittest.skipIf(not _network_available, "Internet not reachable")
class LiveResolverTests(unittest.TestCase):
def testZoneForName1(self):
- name = dns.name.from_text('www.dnspython.org.')
- ezname = dns.name.from_text('dnspython.org.')
+ name = dns.name.from_text("www.dnspython.org.")
+ ezname = dns.name.from_text("dnspython.org.")
zname = dns.resolver.zone_for_name(name)
self.assertEqual(zname, ezname)
def testZoneForName2(self):
- name = dns.name.from_text('a.b.www.dnspython.org.')
- ezname = dns.name.from_text('dnspython.org.')
+ name = dns.name.from_text("a.b.www.dnspython.org.")
+ ezname = dns.name.from_text("dnspython.org.")
zname = dns.resolver.zone_for_name(name)
self.assertEqual(zname, ezname)
def testZoneForName3(self):
- ezname = dns.name.from_text('dnspython.org.')
- zname = dns.resolver.zone_for_name('dnspython.org.')
+ ezname = dns.name.from_text("dnspython.org.")
+ zname = dns.resolver.zone_for_name("dnspython.org.")
self.assertEqual(zname, ezname)
def testZoneForName4(self):
def bad():
- name = dns.name.from_text('dnspython.org', None)
+ name = dns.name.from_text("dnspython.org", None)
dns.resolver.zone_for_name(name)
+
self.assertRaises(dns.resolver.NotAbsolute, bad)
def testResolve(self):
- answer = dns.resolver.resolve('dns.google.', 'A')
+ answer = dns.resolver.resolve("dns.google.", "A")
seen = set([rdata.address for rdata in answer])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testResolveTCP(self):
- answer = dns.resolver.resolve('dns.google.', 'A', tcp=True)
+ answer = dns.resolver.resolve("dns.google.", "A", tcp=True)
seen = set([rdata.address for rdata in answer])
- self.assertTrue('8.8.8.8' in seen)
- self.assertTrue('8.8.4.4' in seen)
+ self.assertTrue("8.8.8.8" in seen)
+ self.assertTrue("8.8.4.4" in seen)
def testResolveAddress(self):
- answer = dns.resolver.resolve_address('8.8.8.8')
- dnsgoogle = dns.name.from_text('dns.google.')
+ answer = dns.resolver.resolve_address("8.8.8.8")
+ dnsgoogle = dns.name.from_text("dns.google.")
self.assertEqual(answer[0].target, dnsgoogle)
- @patch.object(dns.message.Message, 'use_edns')
+ @patch.object(dns.message.Message, "use_edns")
def testResolveEdnsOptions(self, message_use_edns_mock):
resolver = dns.resolver.Resolver()
- options = [dns.edns.ECSOption('1.1.1.1')]
+ options = [dns.edns.ECSOption("1.1.1.1")]
resolver.use_edns(True, options=options)
- resolver.resolve('dns.google.', 'A')
- assert {'options': options} in message_use_edns_mock.call_args
+ resolver.resolve("dns.google.", "A")
+ assert {"options": options} in message_use_edns_mock.call_args
def testResolveNodataException(self):
def bad():
- dns.resolver.resolve('dnspython.org.', 'SRV')
+ dns.resolver.resolve("dnspython.org.", "SRV")
+
self.assertRaises(dns.resolver.NoAnswer, bad)
def testResolveNodataAnswer(self):
- qname = dns.name.from_text('dnspython.org')
- qclass = dns.rdataclass.from_text('IN')
- qtype = dns.rdatatype.from_text('SRV')
+ qname = dns.name.from_text("dnspython.org")
+ qclass = dns.rdataclass.from_text("IN")
+ qtype = dns.rdatatype.from_text("SRV")
answer = dns.resolver.resolve(qname, qtype, raise_on_no_answer=False)
- self.assertRaises(KeyError,
- lambda: answer.response.find_rrset(answer.response.answer,
- qname, qclass, qtype))
+ self.assertRaises(
+ KeyError,
+ lambda: answer.response.find_rrset(
+ answer.response.answer, qname, qclass, qtype
+ ),
+ )
def testResolveNXDOMAIN(self):
- qname = dns.name.from_text('nxdomain.dnspython.org')
- qclass = dns.rdataclass.from_text('IN')
- qtype = dns.rdatatype.from_text('A')
+ qname = dns.name.from_text("nxdomain.dnspython.org")
+ qclass = dns.rdataclass.from_text("IN")
+ qtype = dns.rdatatype.from_text("A")
+
def bad():
answer = dns.resolver.resolve(qname, qtype)
+
try:
dns.resolver.resolve(qname, qtype)
self.assertTrue(False) # should not happen!
def testResolveCacheHit(self):
res = dns.resolver.Resolver(configure=False)
- res.nameservers = ['8.8.8.8']
+ res.nameservers = ["8.8.8.8"]
res.cache = dns.resolver.Cache()
- answer1 = res.resolve('dns.google.', 'A')
+ answer1 = res.resolve("dns.google.", "A")
seen = set([rdata.address for rdata in answer1])
- self.assertIn('8.8.8.8', seen)
- self.assertIn('8.8.4.4', seen)
- answer2 = res.resolve('dns.google.', 'A')
+ self.assertIn("8.8.8.8", seen)
+ self.assertIn("8.8.4.4", seen)
+ answer2 = res.resolve("dns.google.", "A")
self.assertIs(answer2, answer1)
def testCanonicalNameNoCNAME(self):
- cname = dns.name.from_text('www.google.com')
- self.assertEqual(dns.resolver.canonical_name('www.google.com'), cname)
+ cname = dns.name.from_text("www.google.com")
+ self.assertEqual(dns.resolver.canonical_name("www.google.com"), cname)
def testCanonicalNameCNAME(self):
- name = dns.name.from_text('www.dnspython.org')
- cname = dns.name.from_text('dmfrjf4ips8xa.cloudfront.net')
+ name = dns.name.from_text("www.dnspython.org")
+ cname = dns.name.from_text("dmfrjf4ips8xa.cloudfront.net")
self.assertEqual(dns.resolver.canonical_name(name), cname)
@unittest.skipIf(_systemd_resolved_present, "systemd-resolved in use")
def testCanonicalNameDangling(self):
- name = dns.name.from_text('dangling-cname.dnspython.org')
- cname = dns.name.from_text('dangling-target.dnspython.org')
+ name = dns.name.from_text("dangling-cname.dnspython.org")
+ cname = dns.name.from_text("dangling-target.dnspython.org")
self.assertEqual(dns.resolver.canonical_name(name), cname)
def testNameserverSetting(self):
res = dns.resolver.Resolver(configure=False)
- ns = ['1.2.3.4', '::1', 'https://ns.example']
+ ns = ["1.2.3.4", "::1", "https://ns.example"]
res.nameservers = ns[:]
self.assertEqual(res.nameservers, ns)
- for ns in ['999.999.999.999', 'ns.example.', 'bogus://ns.example']:
+ for ns in ["999.999.999.999", "ns.example.", "bogus://ns.example"]:
with self.assertRaises(ValueError):
res.nameservers = [ns]
unittest.TestCase.tearDown(self)
-class SelectResolverTestCase(PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase):
+class SelectResolverTestCase(
+ PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase
+):
def selector_class(self):
return selectors.SelectSelector
-if hasattr(selectors, 'PollSelector'):
- class PollResolverTestCase(PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase):
+if hasattr(selectors, "PollSelector"):
+
+ class PollResolverTestCase(
+ PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase
+ ):
def selector_class(self):
return selectors.PollSelector
# pylint: disable=broad-except
def test_nxdomain_compatible(self):
- n1 = dns.name.Name(('a', 'b', ''))
- n2 = dns.name.Name(('a', 'b', 's', ''))
+ n1 = dns.name.Name(("a", "b", ""))
+ n2 = dns.name.Name(("a", "b", "s", ""))
try:
raise dns.resolver.NXDOMAIN
except dns.exception.DNSException as e:
self.assertEqual(e.args, (e.__doc__,))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), e.__doc__, str(e))
- self.assertTrue(('qnames' not in e.kwargs))
- self.assertTrue(('responses' not in e.kwargs))
+ self.assertTrue(("qnames" not in e.kwargs))
+ self.assertTrue(("responses" not in e.kwargs))
try:
raise dns.resolver.NXDOMAIN("errmsg")
except dns.exception.DNSException as e:
self.assertEqual(e.args, ("errmsg",))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), "errmsg", str(e))
- self.assertTrue(('qnames' not in e.kwargs))
- self.assertTrue(('responses' not in e.kwargs))
+ self.assertTrue(("qnames" not in e.kwargs))
+ self.assertTrue(("responses" not in e.kwargs))
try:
raise dns.resolver.NXDOMAIN("errmsg", -1)
except dns.exception.DNSException as e:
self.assertEqual(e.args, ("errmsg", -1))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), "('errmsg', -1)", str(e))
- self.assertTrue(('qnames' not in e.kwargs))
- self.assertTrue(('responses' not in e.kwargs))
+ self.assertTrue(("qnames" not in e.kwargs))
+ self.assertTrue(("responses" not in e.kwargs))
try:
raise dns.resolver.NXDOMAIN(qnames=None)
except dns.exception.DNSException as e:
MSG = "The DNS query name does not exist: a.b."
self.assertEqual(e.args, (MSG,), repr(e.args))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), MSG, str(e))
- self.assertTrue(('qnames' in e.kwargs))
- self.assertEqual(e.kwargs['qnames'], [n1])
- self.assertTrue(('responses' in e.kwargs))
- self.assertEqual(e.kwargs['responses'], {})
+ self.assertTrue(("qnames" in e.kwargs))
+ self.assertEqual(e.kwargs["qnames"], [n1])
+ self.assertTrue(("responses" in e.kwargs))
+ self.assertEqual(e.kwargs["responses"], {})
try:
raise dns.resolver.NXDOMAIN(qnames=[n2, n1])
e = e0 + e
MSG = "None of DNS query names exist: a.b.s., a.b."
self.assertEqual(e.args, (MSG,), repr(e.args))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), MSG, str(e))
- self.assertTrue(('qnames' in e.kwargs))
- self.assertEqual(e.kwargs['qnames'], [n2, n1])
- self.assertTrue(('responses' in e.kwargs))
- self.assertEqual(e.kwargs['responses'], {})
+ self.assertTrue(("qnames" in e.kwargs))
+ self.assertEqual(e.kwargs["qnames"], [n2, n1])
+ self.assertTrue(("responses" in e.kwargs))
+ self.assertEqual(e.kwargs["responses"], {})
try:
- raise dns.resolver.NXDOMAIN(qnames=[n1], responses=['r1.1'])
+ raise dns.resolver.NXDOMAIN(qnames=[n1], responses=["r1.1"])
except Exception as e:
self.assertTrue((isinstance(e, AttributeError)))
try:
- raise dns.resolver.NXDOMAIN(qnames=[n1], responses={n1: 'r1.1'})
+ raise dns.resolver.NXDOMAIN(qnames=[n1], responses={n1: "r1.1"})
except dns.resolver.NXDOMAIN as e:
MSG = "The DNS query name does not exist: a.b."
self.assertEqual(e.args, (MSG,), repr(e.args))
- self.assertTrue(('kwargs' in dir(e)))
+ self.assertTrue(("kwargs" in dir(e)))
self.assertEqual(str(e), MSG, str(e))
- self.assertTrue(('qnames' in e.kwargs))
- self.assertEqual(e.kwargs['qnames'], [n1])
- self.assertTrue(('responses' in e.kwargs))
- self.assertEqual(e.kwargs['responses'], {n1: 'r1.1'})
+ self.assertTrue(("qnames" in e.kwargs))
+ self.assertEqual(e.kwargs["qnames"], [n1])
+ self.assertTrue(("responses" in e.kwargs))
+ self.assertEqual(e.kwargs["responses"], {n1: "r1.1"})
def test_nxdomain_merge(self):
- n1 = dns.name.Name(('a', 'b', ''))
- n2 = dns.name.Name(('a', 'b', ''))
- n3 = dns.name.Name(('a', 'b', 'c', ''))
- n4 = dns.name.Name(('a', 'b', 'd', ''))
- responses1 = {n1: 'r1.1', n2: 'r1.2', n4: 'r1.4'}
- qnames1 = [n1, n4] # n2 == n1
- responses2 = {n2: 'r2.2', n3: 'r2.3'}
+ n1 = dns.name.Name(("a", "b", ""))
+ n2 = dns.name.Name(("a", "b", ""))
+ n3 = dns.name.Name(("a", "b", "c", ""))
+ n4 = dns.name.Name(("a", "b", "d", ""))
+ responses1 = {n1: "r1.1", n2: "r1.2", n4: "r1.4"}
+ qnames1 = [n1, n4] # n2 == n1
+ responses2 = {n2: "r2.2", n3: "r2.3"}
qnames2 = [n2, n3]
e0 = dns.resolver.NXDOMAIN()
e1 = dns.resolver.NXDOMAIN(qnames=qnames1, responses=responses1)
e2 = dns.resolver.NXDOMAIN(qnames=qnames2, responses=responses2)
e = e1 + e0 + e2
self.assertRaises(AttributeError, lambda: e0 + e0)
- self.assertEqual(e.kwargs['qnames'], [n1, n4, n3],
- repr(e.kwargs['qnames']))
- self.assertTrue(e.kwargs['responses'][n1].startswith('r2.'))
- self.assertTrue(e.kwargs['responses'][n2].startswith('r2.'))
- self.assertTrue(e.kwargs['responses'][n3].startswith('r2.'))
- self.assertTrue(e.kwargs['responses'][n4].startswith('r1.'))
+ self.assertEqual(e.kwargs["qnames"], [n1, n4, n3], repr(e.kwargs["qnames"]))
+ self.assertTrue(e.kwargs["responses"][n1].startswith("r2."))
+ self.assertTrue(e.kwargs["responses"][n2].startswith("r2."))
+ self.assertTrue(e.kwargs["responses"][n3].startswith("r2."))
+ self.assertTrue(e.kwargs["responses"][n4].startswith("r1."))
def test_nxdomain_canonical_name(self):
cname1 = "91.11.8-22.17.172.in-addr.arpa."
class ResolverMiscTestCase(unittest.TestCase):
- if sys.platform != 'win32':
+ if sys.platform != "win32":
+
def test_read_nonexistent_config(self):
res = dns.resolver.Resolver(configure=False)
- pathname = '/etc/nonexistent-resolv.conf'
- self.assertRaises(dns.resolver.NoResolverConfiguration,
- lambda: res.read_resolv_conf(pathname))
+ pathname = "/etc/nonexistent-resolv.conf"
+ self.assertRaises(
+ dns.resolver.NoResolverConfiguration,
+ lambda: res.read_resolv_conf(pathname),
+ )
def test_compute_timeout(self):
res = dns.resolver.Resolver(configure=False)
now = time.time()
- self.assertRaises(dns.resolver.Timeout,
- lambda: res._compute_timeout(now + 10000))
- self.assertRaises(dns.resolver.Timeout,
- lambda: res._compute_timeout(0))
+ self.assertRaises(
+ dns.resolver.Timeout, lambda: res._compute_timeout(now + 10000)
+ )
+ self.assertRaises(dns.resolver.Timeout, lambda: res._compute_timeout(0))
# not raising is the test
res._compute_timeout(now + 0.5)
- if sys.platform == 'win32':
+ if sys.platform == "win32":
+
def test_configure_win32_domain(self):
- n = dns.name.from_text('home.')
- self.assertEqual(n, dns.win32util._config_domain('home'))
- self.assertEqual(n, dns.win32util._config_domain('.home'))
+ n = dns.name.from_text("home.")
+ self.assertEqual(n, dns.win32util._config_domain("home"))
+ self.assertEqual(n, dns.win32util._config_domain(".home"))
class ResolverNameserverValidTypeTestCase(unittest.TestCase):
def test_set_nameservers_to_list(self):
resolver = dns.resolver.Resolver(configure=False)
- resolver.nameservers = ['1.2.3.4']
- self.assertEqual(resolver.nameservers, ['1.2.3.4'])
+ resolver.nameservers = ["1.2.3.4"]
+ self.assertEqual(resolver.nameservers, ["1.2.3.4"])
def test_set_namservers_to_empty_list(self):
resolver = dns.resolver.Resolver(configure=False)
def test_set_nameservers_invalid_type(self):
resolver = dns.resolver.Resolver(configure=False)
- invalid_nameservers = [None, '1.2.3.4', 1234, (1, 2, 3, 4), {'invalid': 'nameserver'}]
+ invalid_nameservers = [
+ None,
+ "1.2.3.4",
+ 1234,
+ (1, 2, 3, 4),
+ {"invalid": "nameserver"},
+ ]
for invalid_nameserver in invalid_nameservers:
with self.assertRaises(ValueError):
resolver.nameservers = invalid_nameserver
class NaptrNanoNameserver(Server):
-
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.REFUSED)
response.flags |= dns.flags.RA
try:
- zero_subdomain = dns.e164.from_e164('0')
+ zero_subdomain = dns.e164.from_e164("0")
if request.qname.is_subdomain(zero_subdomain):
response.set_rcode(dns.rcode.NXDOMAIN)
response.flags |= dns.flags.AA
- elif request.qtype == dns.rdatatype.NAPTR and \
- request.qclass == dns.rdataclass.IN:
- rrs = dns.rrset.from_text(request.qname, 300, 'IN', 'NAPTR',
- '0 0 "" "" "" .')
+ elif (
+ request.qtype == dns.rdatatype.NAPTR
+ and request.qclass == dns.rdataclass.IN
+ ):
+ rrs = dns.rrset.from_text(
+ request.qname, 300, "IN", "NAPTR", '0 0 "" "" "" .'
+ )
response.answer.append(rrs)
response.set_rcode(dns.rcode.NOERROR)
response.flags |= dns.flags.AA
return response
-@unittest.skipIf(not (_network_available and _nanonameserver_available),
- "Internet and NanoAuth required")
+@unittest.skipIf(
+ not (_network_available and _nanonameserver_available),
+ "Internet and NanoAuth required",
+)
class NanoTests(unittest.TestCase):
-
def testE164Query(self):
with NaptrNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
- answer = dns.e164.query('1650551212', ['e164.arpa'], res)
+ answer = dns.e164.query("1650551212", ["e164.arpa"], res)
self.assertEqual(answer[0].order, 0)
self.assertEqual(answer[0].preference, 0)
- self.assertEqual(answer[0].flags, b'')
- self.assertEqual(answer[0].service, b'')
- self.assertEqual(answer[0].regexp, b'')
+ self.assertEqual(answer[0].flags, b"")
+ self.assertEqual(answer[0].service, b"")
+ self.assertEqual(answer[0].regexp, b"")
self.assertEqual(answer[0].replacement, dns.name.root)
with self.assertRaises(dns.resolver.NXDOMAIN):
- dns.e164.query('0123456789', ['e164.arpa'], res)
+ dns.e164.query("0123456789", ["e164.arpa"], res)
class AlwaysType3NXDOMAINNanoNameserver(Server):
-
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.NXDOMAIN)
class AlwaysNXDOMAINNanoNameserver(Server):
-
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.NXDOMAIN)
response.flags |= dns.flags.RA
- origin = dns.name.from_text('example.')
- soa_rrset = response.find_rrset(response.authority, origin,
- dns.rdataclass.IN, dns.rdatatype.SOA,
- create=True)
- rdata = dns.rdata.from_text('IN', 'SOA',
- 'ns.example. root.example. 1 2 3 4 5')
+ origin = dns.name.from_text("example.")
+ soa_rrset = response.find_rrset(
+ response.authority,
+ origin,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ create=True,
+ )
+ rdata = dns.rdata.from_text("IN", "SOA", "ns.example. root.example. 1 2 3 4 5")
soa_rrset.add(rdata)
soa_rrset.update_ttl(300)
return response
-class AlwaysNoErrorNoDataNanoNameserver(Server):
+class AlwaysNoErrorNoDataNanoNameserver(Server):
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.NOERROR)
response.flags |= dns.flags.RA
- origin = dns.name.from_text('example.')
- soa_rrset = response.find_rrset(response.authority, origin,
- dns.rdataclass.IN, dns.rdatatype.SOA,
- create=True)
- rdata = dns.rdata.from_text('IN', 'SOA',
- 'ns.example. root.example. 1 2 3 4 5')
+ origin = dns.name.from_text("example.")
+ soa_rrset = response.find_rrset(
+ response.authority,
+ origin,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ create=True,
+ )
+ rdata = dns.rdata.from_text("IN", "SOA", "ns.example. root.example. 1 2 3 4 5")
soa_rrset.add(rdata)
soa_rrset.update_ttl(300)
return response
-@unittest.skipIf(not (_network_available and _nanonameserver_available),
- "Internet and NanoAuth required")
-class ZoneForNameTests(unittest.TestCase):
+
+@unittest.skipIf(
+ not (_network_available and _nanonameserver_available),
+ "Internet and NanoAuth required",
+)
+class ZoneForNameTests(unittest.TestCase):
def testNoRootSOA(self):
with AlwaysType3NXDOMAINNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
with self.assertRaises(dns.resolver.NoRootSOA):
- dns.resolver.zone_for_name('www.foo.bar.', resolver=res)
+ dns.resolver.zone_for_name("www.foo.bar.", resolver=res)
def testHelpfulNXDOMAIN(self):
with AlwaysNXDOMAINNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
- expected = dns.name.from_text('example.')
- name = dns.resolver.zone_for_name('1.2.3.4.5.6.7.8.9.10.example.',
- resolver=res)
+ expected = dns.name.from_text("example.")
+ name = dns.resolver.zone_for_name(
+ "1.2.3.4.5.6.7.8.9.10.example.", resolver=res
+ )
self.assertEqual(name, expected)
def testHelpfulNoErrorNoData(self):
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
- expected = dns.name.from_text('example.')
- name = dns.resolver.zone_for_name('1.2.3.4.5.6.7.8.9.10.example.',
- resolver=res)
+ expected = dns.name.from_text("example.")
+ name = dns.resolver.zone_for_name(
+ "1.2.3.4.5.6.7.8.9.10.example.", resolver=res
+ )
self.assertEqual(name, expected)
-class DroppingNanoNameserver(Server):
+class DroppingNanoNameserver(Server):
def handle(self, request):
return None
class FormErrNanoNameserver(Server):
-
def handle(self, request):
r = dns.message.make_response(request.message)
r.set_rcode(dns.rcode.FORMERR)
# we use pytest for these so we can have a "slow" mark later if we want to
# (right now it's still fast enough we don't really need it)
-@pytest.mark.skipif(not (_network_available and _nanonameserver_available),
- reason="Internet and NanoAuth required")
+
+@pytest.mark.skipif(
+ not (_network_available and _nanonameserver_available),
+ reason="Internet and NanoAuth required",
+)
def testResolverTimeout():
with DroppingNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.timeout = 0.2
try:
lifetime = 1.0
- a = res.resolve('www.dnspython.org', lifetime=lifetime)
+ a = res.resolve("www.dnspython.org", lifetime=lifetime)
assert False # should never happen
except dns.resolver.LifetimeTimeout as e:
- assert e.kwargs['timeout'] >= lifetime
+ assert e.kwargs["timeout"] >= lifetime
# The length of errors can vary based on how slow things are,
# but it ought to be > 1, so we assert that.
- errors = e.kwargs['errors']
+ errors = e.kwargs["errors"]
assert len(errors) > 1
for error in errors:
assert error[0] == na.udp_address[0] # address
assert error[2] == na.udp_address[1] # port
assert isinstance(error[3], dns.exception.Timeout) # exception
-@pytest.mark.skipif(not (_network_available and _nanonameserver_available),
- reason="Internet and NanoAuth required")
+
+@pytest.mark.skipif(
+ not (_network_available and _nanonameserver_available),
+ reason="Internet and NanoAuth required",
+)
def testResolverNoNameservers():
with FormErrNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
try:
- a = res.resolve('www.dnspython.org')
+ a = res.resolve("www.dnspython.org")
assert False # should never happen
except dns.resolver.NoNameservers as e:
- errors = e.kwargs['errors']
+ errors = e.kwargs["errors"]
assert len(errors) == 1
for error in errors:
assert error[0] == na.udp_address[0] # address
assert not error[1] # not TCP
assert error[2] == na.udp_address[1] # port
- assert error[3] == 'FORMERR'
+ assert error[3] == "FORMERR"
class SlowAlwaysType3NXDOMAINNanoNameserver(Server):
-
def handle(self, request):
response = dns.message.make_response(request.message)
response.set_rcode(dns.rcode.NXDOMAIN)
return response
-@pytest.mark.skipif(not (_network_available and _nanonameserver_available),
- reason="Internet and NanoAuth required")
+@pytest.mark.skipif(
+ not (_network_available and _nanonameserver_available),
+ reason="Internet and NanoAuth required",
+)
def testZoneForNameLifetimeTimeout():
with SlowAlwaysType3NXDOMAINNanoNameserver() as na:
res = dns.resolver.Resolver(configure=False)
res.port = na.udp_address[1]
res.nameservers = [na.udp_address[0]]
with pytest.raises(dns.resolver.LifetimeTimeout):
- dns.resolver.zone_for_name('1.2.3.4.5.6.7.8.9.10.example.',
- resolver=res, lifetime=1.0)
+ dns.resolver.zone_for_name(
+ "1.2.3.4.5.6.7.8.9.10.example.", resolver=res, lifetime=1.0
+ )
# skip those if it's not there.
_network_available = True
try:
- socket.gethostbyname('dnspython.org')
+ socket.gethostbyname("dnspython.org")
except socket.gaierror:
_network_available = False
@unittest.skipIf(not _network_available, "Internet not reachable")
class OverrideSystemResolverTestCase(unittest.TestCase):
-
def setUp(self):
self.res = dns.resolver.Resolver(configure=False)
- self.res.nameservers = ['8.8.8.8']
+ self.res.nameservers = ["8.8.8.8"]
self.res.cache = dns.resolver.LRUCache()
dns.resolver.override_system_resolver(self.res)
self.res = None
def test_override(self):
- self.assertTrue(socket.getaddrinfo is
- dns.resolver._getaddrinfo)
- socket.gethostbyname('www.dnspython.org')
- answer = self.res.cache.get((dns.name.from_text('www.dnspython.org.'),
- dns.rdatatype.A, dns.rdataclass.IN))
+ self.assertTrue(socket.getaddrinfo is dns.resolver._getaddrinfo)
+ socket.gethostbyname("www.dnspython.org")
+ answer = self.res.cache.get(
+ (
+ dns.name.from_text("www.dnspython.org."),
+ dns.rdatatype.A,
+ dns.rdataclass.IN,
+ )
+ )
self.assertTrue(answer is not None)
self.res.cache.flush()
- socket.gethostbyname_ex('www.dnspython.org')
- answer = self.res.cache.get((dns.name.from_text('www.dnspython.org.'),
- dns.rdatatype.A, dns.rdataclass.IN))
+ socket.gethostbyname_ex("www.dnspython.org")
+ answer = self.res.cache.get(
+ (
+ dns.name.from_text("www.dnspython.org."),
+ dns.rdatatype.A,
+ dns.rdataclass.IN,
+ )
+ )
self.assertTrue(answer is not None)
self.res.cache.flush()
- socket.getfqdn('8.8.8.8')
+ socket.getfqdn("8.8.8.8")
answer = self.res.cache.get(
- (dns.name.from_text('8.8.8.8.in-addr.arpa.'),
- dns.rdatatype.PTR, dns.rdataclass.IN))
+ (
+ dns.name.from_text("8.8.8.8.in-addr.arpa."),
+ dns.rdatatype.PTR,
+ dns.rdataclass.IN,
+ )
+ )
self.assertTrue(answer is not None)
self.res.cache.flush()
- socket.gethostbyaddr('8.8.8.8')
+ socket.gethostbyaddr("8.8.8.8")
answer = self.res.cache.get(
- (dns.name.from_text('8.8.8.8.in-addr.arpa.'),
- dns.rdatatype.PTR, dns.rdataclass.IN))
+ (
+ dns.name.from_text("8.8.8.8.in-addr.arpa."),
+ dns.rdatatype.PTR,
+ dns.rdataclass.IN,
+ )
+ )
self.assertTrue(answer is not None)
# restoring twice is harmless, so we restore now instead of
# waiting for tearDown so we can assert that it worked
dns.resolver.restore_system_resolver()
- self.assertTrue(socket.getaddrinfo is
- dns.resolver._original_getaddrinfo)
+ self.assertTrue(socket.getaddrinfo is dns.resolver._original_getaddrinfo)
def equivalent_info(self, a, b):
if len(a) != len(b):
# looking for a zero protocol.
y = (x[0], x[1], 0, x[3], x[4])
if y not in b:
- print('NOT EQUIVALENT')
+ print("NOT EQUIVALENT")
print(a)
print(b)
return False
b = dns.resolver._original_getaddrinfo(*args, **kwargs)
return self.equivalent_info(a, b)
- @unittest.skipIf(sys.platform == 'win32',
- 'avoid windows original getaddrinfo issues')
+ @unittest.skipIf(
+ sys.platform == "win32", "avoid windows original getaddrinfo issues"
+ )
def test_basic_getaddrinfo(self):
- self.assertTrue(self.equivalent('dns.google', 53, socket.AF_INET,
- socket.SOCK_DGRAM))
- self.assertTrue(self.equivalent('dns.google', 53, socket.AF_INET6,
- socket.SOCK_DGRAM))
- self.assertTrue(self.equivalent('dns.google', None, socket.AF_UNSPEC,
- socket.SOCK_DGRAM))
- self.assertTrue(self.equivalent('8.8.8.8', 53, socket.AF_INET,
- socket.SOCK_DGRAM))
- self.assertTrue(self.equivalent('2001:4860:4860::8888', 53,
- socket.AF_INET6, socket.SOCK_DGRAM))
- self.assertTrue(self.equivalent('8.8.8.8', 53, socket.AF_INET,
- socket.SOCK_DGRAM,
- flags=socket.AI_NUMERICHOST))
- self.assertTrue(self.equivalent('2001:4860:4860::8888', 53,
- socket.AF_INET6, socket.SOCK_DGRAM,
- flags=socket.AI_NUMERICHOST))
+ self.assertTrue(
+ self.equivalent("dns.google", 53, socket.AF_INET, socket.SOCK_DGRAM)
+ )
+ self.assertTrue(
+ self.equivalent("dns.google", 53, socket.AF_INET6, socket.SOCK_DGRAM)
+ )
+ self.assertTrue(
+ self.equivalent("dns.google", None, socket.AF_UNSPEC, socket.SOCK_DGRAM)
+ )
+ self.assertTrue(
+ self.equivalent("8.8.8.8", 53, socket.AF_INET, socket.SOCK_DGRAM)
+ )
+ self.assertTrue(
+ self.equivalent(
+ "2001:4860:4860::8888", 53, socket.AF_INET6, socket.SOCK_DGRAM
+ )
+ )
+ self.assertTrue(
+ self.equivalent(
+ "8.8.8.8",
+ 53,
+ socket.AF_INET,
+ socket.SOCK_DGRAM,
+ flags=socket.AI_NUMERICHOST,
+ )
+ )
+ self.assertTrue(
+ self.equivalent(
+ "2001:4860:4860::8888",
+ 53,
+ socket.AF_INET6,
+ socket.SOCK_DGRAM,
+ flags=socket.AI_NUMERICHOST,
+ )
+ )
def test_getaddrinfo_nxdomain(self):
try:
- socket.getaddrinfo('nxdomain.dnspython.org.', 53)
- self.assertTrue(False) # should not happen!
+ socket.getaddrinfo("nxdomain.dnspython.org.", 53)
+ self.assertTrue(False) # should not happen!
except socket.gaierror as e:
self.assertEqual(e.errno, socket.EAI_NONAME)
def test_getaddrinfo_service(self):
- a = socket.getaddrinfo('dns.google', 'domain')
- b = socket.getaddrinfo('dns.google', 53)
+ a = socket.getaddrinfo("dns.google", "domain")
+ b = socket.getaddrinfo("dns.google", 53)
self.assertTrue(self.equivalent_info(a, b))
try:
- socket.getaddrinfo('dns.google', 'domain',
- flags=socket.AI_NUMERICSERV)
- self.assertTrue(False) # should not happen!
+ socket.getaddrinfo("dns.google", "domain", flags=socket.AI_NUMERICSERV)
+ self.assertTrue(False) # should not happen!
except socket.gaierror as e:
self.assertEqual(e.errno, socket.EAI_NONAME)
def test_getaddrinfo_only_service(self):
- infos = socket.getaddrinfo(service=53, family=socket.AF_INET,
- socktype=socket.SOCK_DGRAM,
- proto=socket.IPPROTO_UDP)
+ infos = socket.getaddrinfo(
+ service=53,
+ family=socket.AF_INET,
+ socktype=socket.SOCK_DGRAM,
+ proto=socket.IPPROTO_UDP,
+ )
self.assertEqual(len(infos), 1)
info = infos[0]
self.assertEqual(info[0], socket.AF_INET)
self.assertEqual(info[1], socket.SOCK_DGRAM)
self.assertEqual(info[2], socket.IPPROTO_UDP)
- self.assertEqual(info[4], ('127.0.0.1', 53))
+ self.assertEqual(info[4], ("127.0.0.1", 53))
def test_unknown_service_fails(self):
with self.assertRaises(socket.gaierror):
- socket.getaddrinfo('dns.google.', 'bogus-service')
+ socket.getaddrinfo("dns.google.", "bogus-service")
def test_getnameinfo_tcp(self):
- info = socket.getnameinfo(('8.8.8.8', 53))
- self.assertEqual(info, ('dns.google', 'domain'))
+ info = socket.getnameinfo(("8.8.8.8", 53))
+ self.assertEqual(info, ("dns.google", "domain"))
def test_getnameinfo_udp(self):
- info = socket.getnameinfo(('8.8.8.8', 53), socket.NI_DGRAM)
- self.assertEqual(info, ('dns.google', 'domain'))
-
-
-# Give up on testing this for now as all of the names I've considered
-# using for testing are part of CDNs and there is deep magic in
-# gethostbyaddr() that python's getfqdn() is using. At any rate,
-# the problem is that dnspython just gives up whereas the native python
-# code is looking up www.dnspython.org, picking a CDN IPv4 address
-# (sometimes) and returning the reverse lookup of that address (i.e.
-# the domain name of the CDN server). This isn't what I'd consider the
-# FQDN of www.dnspython.org to be!
-#
-# def test_getfqdn(self):
-# b = socket.getfqdn('www.dnspython.org')
-# # we do this now because python's original getfqdn calls
-# # gethostbyaddr() and we don't want it to call us!
-# dns.resolver.restore_system_resolver()
-# a = dns.resolver._original_getfqdn('www.dnspython.org')
-# self.assertEqual(dns.name.from_text(a), dns.name.from_text(b))
+ info = socket.getnameinfo(("8.8.8.8", 53), socket.NI_DGRAM)
+ self.assertEqual(info, ("dns.google", "domain"))
+
+ # Give up on testing this for now as all of the names I've considered
+ # using for testing are part of CDNs and there is deep magic in
+ # gethostbyaddr() that python's getfqdn() is using. At any rate,
+ # the problem is that dnspython just gives up whereas the native python
+ # code is looking up www.dnspython.org, picking a CDN IPv4 address
+ # (sometimes) and returning the reverse lookup of that address (i.e.
+ # the domain name of the CDN server). This isn't what I'd consider the
+ # FQDN of www.dnspython.org to be!
+ #
+ # def test_getfqdn(self):
+ # b = socket.getfqdn('www.dnspython.org')
+ # # we do this now because python's original getfqdn calls
+ # # gethostbyaddr() and we don't want it to call us!
+ # dns.resolver.restore_system_resolver()
+ # a = dns.resolver._original_getfqdn('www.dnspython.org')
+ # self.assertEqual(dns.name.from_text(a), dns.name.from_text(b))
def test_gethostbyaddr(self):
- a = dns.resolver._original_gethostbyaddr('8.8.8.8')
- b = socket.gethostbyaddr('8.8.8.8')
+ a = dns.resolver._original_gethostbyaddr("8.8.8.8")
+ b = socket.gethostbyaddr("8.8.8.8")
# We only test elements 0 and 2 as we don't set aliases currently!
self.assertEqual(a[0], b[0])
self.assertEqual(a[2], b[2])
- a = dns.resolver._original_gethostbyaddr('2001:4860:4860::8888')
- b = socket.gethostbyaddr('2001:4860:4860::8888')
+ a = dns.resolver._original_gethostbyaddr("2001:4860:4860::8888")
+ b = socket.gethostbyaddr("2001:4860:4860::8888")
self.assertEqual(a[0], b[0])
self.assertEqual(a[2], b[2])
class OverrideSystemResolverUsingFakeResolverTestCase(unittest.TestCase):
-
def setUp(self):
self.res = FakeResolver()
dns.resolver.override_system_resolver(self.res)
def test_temporary_failure(self):
with self.assertRaises(socket.gaierror):
- socket.getaddrinfo('dns.google')
+ socket.getaddrinfo("dns.google")
# We don't need the fake resolver for the following tests, but we
# don't need the live network either, so we're testing here.
def test_AI_ADDRCONFIG_fails(self):
with self.assertRaises(socket.gaierror):
- socket.getaddrinfo('dns.google', flags=socket.AI_ADDRCONFIG)
+ socket.getaddrinfo("dns.google", flags=socket.AI_ADDRCONFIG)
def test_gethostbyaddr_of_name_fails(self):
with self.assertRaises(socket.gaierror):
- socket.gethostbyaddr('bogus')
+ socket.gethostbyaddr("bogus")
@unittest.skipIf(not _network_available, "Internet not reachable")
class OverrideSystemResolverUsingDefaultResolverTestCase(unittest.TestCase):
-
def setUp(self):
self.res = FakeResolver()
dns.resolver.override_system_resolver()
import dns.name
import dns.rrset
-class RRsetTestCase(unittest.TestCase):
+class RRsetTestCase(unittest.TestCase):
def testEqual1(self):
- r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2')
- r2 = dns.rrset.from_text('FOO', 300, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1", "10.0.0.2")
+ r2 = dns.rrset.from_text("FOO", 300, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertEqual(r1, r2)
def testEqual2(self):
- r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2')
- r2 = dns.rrset.from_text('FOO', 600, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1", "10.0.0.2")
+ r2 = dns.rrset.from_text("FOO", 600, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertEqual(r1, r2)
def testNotEqual1(self):
- r1 = dns.rrset.from_text('fooa', 30, 'in', 'a', '10.0.0.1', '10.0.0.2')
- r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text("fooa", 30, "in", "a", "10.0.0.1", "10.0.0.2")
+ r2 = dns.rrset.from_text("FOO", 30, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertNotEqual(r1, r2)
def testNotEqual2(self):
- r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.3')
- r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text("foo", 30, "in", "a", "10.0.0.1", "10.0.0.3")
+ r2 = dns.rrset.from_text("FOO", 30, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertNotEqual(r1, r2)
def testNotEqual3(self):
- r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.2',
- '10.0.0.3')
- r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text(
+ "foo", 30, "in", "a", "10.0.0.1", "10.0.0.2", "10.0.0.3"
+ )
+ r2 = dns.rrset.from_text("FOO", 30, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertNotEqual(r1, r2)
def testNotEqual4(self):
- r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1')
- r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
+ r1 = dns.rrset.from_text("foo", 30, "in", "a", "10.0.0.1")
+ r2 = dns.rrset.from_text("FOO", 30, "in", "a", "10.0.0.2", "10.0.0.1")
self.assertNotEqual(r1, r2)
def testCodec2003(self):
- r1 = dns.rrset.from_text_list('Königsgäßchen', 30, 'in', 'ns',
- ['Königsgäßchen'])
- r2 = dns.rrset.from_text_list('xn--knigsgsschen-lcb0w', 30, 'in', 'ns',
- ['xn--knigsgsschen-lcb0w'])
+ r1 = dns.rrset.from_text_list(
+ "Königsgäßchen", 30, "in", "ns", ["Königsgäßchen"]
+ )
+ r2 = dns.rrset.from_text_list(
+ "xn--knigsgsschen-lcb0w", 30, "in", "ns", ["xn--knigsgsschen-lcb0w"]
+ )
self.assertEqual(r1, r2)
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testCodec2008(self):
- r1 = dns.rrset.from_text_list('Königsgäßchen', 30, 'in', 'ns',
- ['Königsgäßchen'],
- idna_codec=dns.name.IDNA_2008)
- r2 = dns.rrset.from_text_list('xn--knigsgchen-b4a3dun', 30, 'in', 'ns',
- ['xn--knigsgchen-b4a3dun'],
- idna_codec=dns.name.IDNA_2008)
+ r1 = dns.rrset.from_text_list(
+ "Königsgäßchen",
+ 30,
+ "in",
+ "ns",
+ ["Königsgäßchen"],
+ idna_codec=dns.name.IDNA_2008,
+ )
+ r2 = dns.rrset.from_text_list(
+ "xn--knigsgchen-b4a3dun",
+ 30,
+ "in",
+ "ns",
+ ["xn--knigsgchen-b4a3dun"],
+ idna_codec=dns.name.IDNA_2008,
+ )
self.assertEqual(r1, r2)
def testCopy(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
r2 = r1.copy()
self.assertFalse(r1 is r2)
self.assertTrue(r1 == r2)
def testFullMatch1(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- self.assertTrue(r1.full_match(r1.name, dns.rdataclass.IN,
- dns.rdatatype.A, dns.rdatatype.NONE))
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ self.assertTrue(
+ r1.full_match(
+ r1.name, dns.rdataclass.IN, dns.rdatatype.A, dns.rdatatype.NONE
+ )
+ )
def testFullMatch2(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
r1.deleting = dns.rdataclass.NONE
- self.assertTrue(r1.full_match(r1.name, dns.rdataclass.IN,
- dns.rdatatype.A, dns.rdatatype.NONE,
- dns.rdataclass.NONE))
+ self.assertTrue(
+ r1.full_match(
+ r1.name,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ dns.rdatatype.NONE,
+ dns.rdataclass.NONE,
+ )
+ )
def testNoFullMatch1(self):
- n = dns.name.from_text('bar', None)
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- self.assertFalse(r1.full_match(n, dns.rdataclass.IN,
- dns.rdatatype.A, dns.rdatatype.NONE,
- dns.rdataclass.ANY))
+ n = dns.name.from_text("bar", None)
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ self.assertFalse(
+ r1.full_match(
+ n,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ dns.rdatatype.NONE,
+ dns.rdataclass.ANY,
+ )
+ )
def testNoFullMatch2(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
r1.deleting = dns.rdataclass.NONE
- self.assertFalse(r1.full_match(r1.name, dns.rdataclass.IN,
- dns.rdatatype.A, dns.rdatatype.NONE,
- dns.rdataclass.ANY))
+ self.assertFalse(
+ r1.full_match(
+ r1.name,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ dns.rdatatype.NONE,
+ dns.rdataclass.ANY,
+ )
+ )
def testNoFullMatch3(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- self.assertFalse(r1.full_match(r1.name, dns.rdataclass.IN,
- dns.rdatatype.MX, dns.rdatatype.NONE,
- dns.rdataclass.ANY))
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ self.assertFalse(
+ r1.full_match(
+ r1.name,
+ dns.rdataclass.IN,
+ dns.rdatatype.MX,
+ dns.rdatatype.NONE,
+ dns.rdataclass.ANY,
+ )
+ )
def testMatchCompatibilityWithFullMatch(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- self.assertTrue(r1.match(r1.name, dns.rdataclass.IN,
- dns.rdatatype.A, dns.rdatatype.NONE))
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ self.assertTrue(
+ r1.match(r1.name, dns.rdataclass.IN, dns.rdatatype.A, dns.rdatatype.NONE)
+ )
def testMatchCompatibilityWithRdatasetMatch(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- self.assertTrue(r1.match(dns.rdataclass.IN, dns.rdatatype.A,
- dns.rdatatype.NONE))
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ self.assertTrue(
+ r1.match(dns.rdataclass.IN, dns.rdatatype.A, dns.rdatatype.NONE)
+ )
def testToRdataset(self):
- r1 = dns.rrset.from_text_list('foo', 30, 'in', 'a',
- ['10.0.0.1', '10.0.0.2'])
- r2 = dns.rdataset.from_text_list('in', 'a', 30,
- ['10.0.0.1', '10.0.0.2'])
+ r1 = dns.rrset.from_text_list("foo", 30, "in", "a", ["10.0.0.1", "10.0.0.2"])
+ r2 = dns.rdataset.from_text_list("in", "a", 30, ["10.0.0.1", "10.0.0.2"])
self.assertEqual(r1.to_rdataset(), r2)
def testFromRdata(self):
- rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
- expected_rrs = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1',
- '10.0.0.2')
- rrs = dns.rrset.from_rdata('foo', 300, rdata1, rdata2)
+ rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
+ expected_rrs = dns.rrset.from_text(
+ "foo", 300, "in", "a", "10.0.0.1", "10.0.0.2"
+ )
+ rrs = dns.rrset.from_rdata("foo", 300, rdata1, rdata2)
self.assertEqual(rrs, expected_rrs)
def testEmptyList(self):
def bad():
- rrs = dns.rrset.from_rdata_list('foo', 300, [])
+ rrs = dns.rrset.from_rdata_list("foo", 300, [])
+
self.assertRaises(ValueError, bad)
def testTTLMinimization(self):
- rrs = dns.rrset.RRset(dns.name.from_text('foo'),
- dns.rdataclass.IN, dns.rdatatype.A)
- rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
+ rrs = dns.rrset.RRset(
+ dns.name.from_text("foo"), dns.rdataclass.IN, dns.rdatatype.A
+ )
+ rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
rrs.add(rdata1, 300)
self.assertEqual(rrs.ttl, 300)
rrs.add(rdata2, 30)
self.assertEqual(rrs.ttl, 3)
def testNotEqualOtherType(self):
- rrs = dns.rrset.RRset(dns.name.from_text('foo'),
- dns.rdataclass.IN, dns.rdatatype.A)
+ rrs = dns.rrset.RRset(
+ dns.name.from_text("foo"), dns.rdataclass.IN, dns.rdatatype.A
+ )
self.assertFalse(rrs == 123)
def testRepr(self):
- rrset = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1',
- '10.0.0.2')
- self.assertEqual(repr(rrset),
- '<DNS foo IN A RRset: [<10.0.0.1>, <10.0.0.2>]>')
+ rrset = dns.rrset.from_text("foo", 30, "in", "a", "10.0.0.1", "10.0.0.2")
+ self.assertEqual(repr(rrset), "<DNS foo IN A RRset: [<10.0.0.1>, <10.0.0.2>]>")
rrset.deleting = dns.rdataclass.NONE
- self.assertEqual(repr(rrset),
- '<DNS foo IN A delete=NONE RRset: ' +
- '[<10.0.0.1>, <10.0.0.2>]>')
+ self.assertEqual(
+ repr(rrset),
+ "<DNS foo IN A delete=NONE RRset: " + "[<10.0.0.1>, <10.0.0.2>]>",
+ )
rrset = dns.rrset.from_text(
- 'foo', 30, 'in', 'rrsig',
- 'A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM=')
- self.assertEqual(repr(rrset),
- '<DNS foo IN RRSIG(A) RRset: ' +
- '[<A 1 3 3600 20200701000000 20200601000000 ' +
- '1 NAME Ym9ndXM=>]>')
-
-if __name__ == '__main__':
+ "foo",
+ 30,
+ "in",
+ "rrsig",
+ "A 1 3 3600 20200701000000 20200601000000 1 NAME Ym9ndXM=",
+ )
+ self.assertEqual(
+ repr(rrset),
+ "<DNS foo IN RRSIG(A) RRset: "
+ + "[<A 1 3 3600 20200701000000 20200601000000 "
+ + "1 NAME Ym9ndXM=>]>",
+ )
+
+
+if __name__ == "__main__":
unittest.main()
import dns.rrset
from dns.zonefile import read_rrsets
-expected_mx_1= dns.rrset.from_text('name.', 300, 'in', 'mx', '10 a.', '20 b.')
-expected_mx_2 = dns.rrset.from_text('name.', 10, 'in', 'mx', '10 a.', '20 b.')
-expected_mx_3 = dns.rrset.from_text('foo.', 10, 'in', 'mx', '10 a.')
-expected_mx_4 = dns.rrset.from_text('bar.', 10, 'in', 'mx', '20 b.')
-expected_mx_5 = dns.rrset.from_text('foo.example.', 10, 'in', 'mx',
- '10 a.example.')
-expected_mx_6 = dns.rrset.from_text('bar.example.', 10, 'in', 'mx', '20 b.')
-expected_mx_7 = dns.rrset.from_text('foo', 10, 'in', 'mx', '10 a')
-expected_mx_8 = dns.rrset.from_text('bar', 10, 'in', 'mx', '20 b.')
-expected_ns_1 = dns.rrset.from_text('name.', 300, 'in', 'ns', 'hi.')
-expected_ns_2 = dns.rrset.from_text('name.', 300, 'ch', 'ns', 'hi.')
+expected_mx_1 = dns.rrset.from_text("name.", 300, "in", "mx", "10 a.", "20 b.")
+expected_mx_2 = dns.rrset.from_text("name.", 10, "in", "mx", "10 a.", "20 b.")
+expected_mx_3 = dns.rrset.from_text("foo.", 10, "in", "mx", "10 a.")
+expected_mx_4 = dns.rrset.from_text("bar.", 10, "in", "mx", "20 b.")
+expected_mx_5 = dns.rrset.from_text("foo.example.", 10, "in", "mx", "10 a.example.")
+expected_mx_6 = dns.rrset.from_text("bar.example.", 10, "in", "mx", "20 b.")
+expected_mx_7 = dns.rrset.from_text("foo", 10, "in", "mx", "10 a")
+expected_mx_8 = dns.rrset.from_text("bar", 10, "in", "mx", "20 b.")
+expected_ns_1 = dns.rrset.from_text("name.", 300, "in", "ns", "hi.")
+expected_ns_2 = dns.rrset.from_text("name.", 300, "ch", "ns", "hi.")
+
def equal_rrsets(a, b):
# return True iff. a and b have the same rrsets regardless of order
return False
return True
+
def test_name_ttl_rdclass_forced():
- input=''';
+ input = """;
mx 10 a
mx 20 b.
-ns hi'''
- rrsets = read_rrsets(input, name='name', ttl=300)
+ns hi"""
+ rrsets = read_rrsets(input, name="name", ttl=300)
assert equal_rrsets(rrsets, [expected_mx_1, expected_ns_1])
assert rrsets[0].ttl == 300
assert rrsets[1].ttl == 300
+
def test_name_ttl_rdclass_forced_rdata_split():
- input=''';
+ input = """;
mx 10 a
ns hi
-mx 20 b.'''
- rrsets = read_rrsets(input, name='name', ttl=300)
+mx 20 b."""
+ rrsets = read_rrsets(input, name="name", ttl=300)
assert equal_rrsets(rrsets, [expected_mx_1, expected_ns_1])
+
def test_name_ttl_rdclass_rdtype_forced():
- input=''';
+ input = """;
10 a
-20 b.'''
- rrsets = read_rrsets(input, name='name', ttl=300, rdtype='mx')
+20 b."""
+ rrsets = read_rrsets(input, name="name", ttl=300, rdtype="mx")
assert equal_rrsets(rrsets, [expected_mx_1])
+
def test_name_rdclass_forced():
- input = '''30 mx 10 a
+ input = """30 mx 10 a
10 mx 20 b.
-'''
- rrsets = read_rrsets(input, name='name')
+"""
+ rrsets = read_rrsets(input, name="name")
assert equal_rrsets(rrsets, [expected_mx_2])
assert rrsets[0].ttl == 10
+
def test_rdclass_forced():
- input = ''';
+ input = """;
foo 20 mx 10 a
bar 30 mx 20 b.
-'''
+"""
rrsets = read_rrsets(input)
assert equal_rrsets(rrsets, [expected_mx_3, expected_mx_4])
+
def test_rdclass_forced_with_origin():
- input = ''';
+ input = """;
foo 20 mx 10 a
bar.example. 30 mx 20 b.
-'''
- rrsets = read_rrsets(input, origin='example')
+"""
+ rrsets = read_rrsets(input, origin="example")
assert equal_rrsets(rrsets, [expected_mx_5, expected_mx_6])
def test_rdclass_forced_with_origin_relativized():
- input = ''';
+ input = """;
foo 20 mx 10 a.example.
bar.example. 30 mx 20 b.
-'''
- rrsets = read_rrsets(input, origin='example', relativize=True)
+"""
+ rrsets = read_rrsets(input, origin="example", relativize=True)
assert equal_rrsets(rrsets, [expected_mx_7, expected_mx_8])
+
def test_rdclass_matching_default_tolerated():
- input = ''';
+ input = """;
foo 20 mx 10 a.example.
bar.example. 30 in mx 20 b.
-'''
- rrsets = read_rrsets(input, origin='example', relativize=True,
- rdclass=None)
+"""
+ rrsets = read_rrsets(input, origin="example", relativize=True, rdclass=None)
assert equal_rrsets(rrsets, [expected_mx_7, expected_mx_8])
+
def test_rdclass_not_matching_default_rejected():
- input = ''';
+ input = """;
foo 20 mx 10 a.example.
bar.example. 30 ch mx 20 b.
-'''
+"""
with pytest.raises(dns.exception.SyntaxError):
- rrsets = read_rrsets(input, origin='example', relativize=True,
- rdclass=None)
+ rrsets = read_rrsets(input, origin="example", relativize=True, rdclass=None)
+
def test_default_rdclass_is_none():
- input = ''
+ input = ""
with pytest.raises(TypeError):
- rrsets = read_rrsets(input, default_rdclass=None, origin='example',
- relativize=True)
+ rrsets = read_rrsets(
+ input, default_rdclass=None, origin="example", relativize=True
+ )
+
def test_name_rdclass_rdtype_force():
# No real-world usage should do this, but it can be specified so we test it.
- input = ''';
+ input = """;
30 10 a
10 20 b.
-'''
- rrsets = read_rrsets(input, name='name', rdtype='mx')
+"""
+ rrsets = read_rrsets(input, name="name", rdtype="mx")
assert equal_rrsets(rrsets, [expected_mx_1])
assert rrsets[0].ttl == 10
+
def test_rdclass_rdtype_force():
# No real-world usage should do this, but it can be specified so we test it.
- input = ''';
+ input = """;
foo 30 10 a
bar 30 20 b.
-'''
- rrsets = read_rrsets(input, rdtype='mx')
+"""
+ rrsets = read_rrsets(input, rdtype="mx")
assert equal_rrsets(rrsets, [expected_mx_3, expected_mx_4])
+
# also weird but legal
-#input5 = '''foo 30 10 a
-#bar 10 20 foo.
+# input5 = '''foo 30 10 a
+# bar 10 20 foo.
#'''
import dns.serial
+
def S2(v):
return dns.serial.Serial(v, bits=2)
+
def S8(v):
return dns.serial.Serial(v, bits=8)
+
class SerialTestCase(unittest.TestCase):
def test_rfc_1982_2_bit_cases(self):
self.assertEqual(S2(0) + S2(1), S2(1))
def test_addition_bounds(self):
self.assertRaises(ValueError, lambda: S8(0) + 128)
self.assertRaises(ValueError, lambda: S8(0) - 128)
+
def bad1():
v = S8(0)
v += 128
+
self.assertRaises(ValueError, bad1)
+
def bad2():
v = S8(0)
v -= 128
+
self.assertRaises(ValueError, bad2)
def test_casting(self):
self.assertTrue(S8(0) >= 255)
def test_uncastable(self):
- self.assertRaises(ValueError, lambda: S8(0) + 'a')
- self.assertRaises(ValueError, lambda: S8(0) - 'a')
+ self.assertRaises(ValueError, lambda: S8(0) + "a")
+ self.assertRaises(ValueError, lambda: S8(0) - "a")
+
def bad1():
v = S8(0)
- v += 'a'
+ v += "a"
+
self.assertRaises(ValueError, bad1)
+
def bad2():
v = S8(0)
- v -= 'a'
+ v -= "a"
+
self.assertRaises(ValueError, bad2)
def test_uncomparable(self):
self.assertFalse(S8(0) == S2(0))
- self.assertFalse(S8(0) == 'a')
- self.assertTrue(S8(0) != 'a')
- self.assertRaises(TypeError, lambda: S8(0) < 'a')
- self.assertRaises(TypeError, lambda: S8(0) <= 'a')
- self.assertRaises(TypeError, lambda: S8(0) > 'a')
- self.assertRaises(TypeError, lambda: S8(0) >= 'a')
+ self.assertFalse(S8(0) == "a")
+ self.assertTrue(S8(0) != "a")
+ self.assertRaises(TypeError, lambda: S8(0) < "a")
+ self.assertRaises(TypeError, lambda: S8(0) <= "a")
+ self.assertRaises(TypeError, lambda: S8(0) > "a")
+ self.assertRaises(TypeError, lambda: S8(0) >= "a")
def test_modulo(self):
self.assertEqual(S8(-1), 255)
self.assertEqual(S8(257), 1)
def test_repr(self):
- self.assertEqual(repr(S8(1)), 'dns.serial.Serial(1, 8)')
+ self.assertEqual(repr(S8(1)), "dns.serial.Serial(1, 8)")
def test_not_equal(self):
self.assertNotEqual(S8(0), S8(1))
# for convenience
S = dns.set.Set
-class SetTestCase(unittest.TestCase):
+class SetTestCase(unittest.TestCase):
def testLen1(self):
s1 = S()
self.assertEqual(len(s1), 0)
s &= S([1, 2])
self.assertEqual(s, S([1, 2]))
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
from tests.util import here
+
class SVCBTestCase(unittest.TestCase):
def check_valid_inputs(self, inputs):
expected = inputs[0]
for text in inputs:
- rr = dns.rdata.from_text('IN', 'SVCB', text)
+ rr = dns.rdata.from_text("IN", "SVCB", text)
new_text = rr.to_text()
self.assertEqual(expected, new_text)
def check_invalid_inputs(self, inputs):
for text in inputs:
with self.assertRaises((dns.exception.SyntaxError, ValueError)):
- dns.rdata.from_text('IN', 'SVCB', text)
+ dns.rdata.from_text("IN", "SVCB", text)
def test_svcb_general_invalid(self):
invalid_inputs = (
"1 . alpn=h2 alpn=h3",
"1 . alpn=h2 key1=h3",
# Quoted keys
- "1 . \"alpn=h2\"",
+ '1 . "alpn=h2"',
# Invalid space
"1 . alpn= h2",
"1 . alpn =h2",
"1 . alpn = h2",
- "1 . alpn= \"h2\"",
+ '1 . alpn= "h2"',
"1 . =alpn",
)
self.check_invalid_inputs(invalid_inputs)
def test_svcb_mandatory(self):
valid_inputs = (
- "1 . mandatory=\"alpn,no-default-alpn\" alpn=\"h2\" no-default-alpn",
+ '1 . mandatory="alpn,no-default-alpn" alpn="h2" no-default-alpn',
"1 . mandatory=alpn,no-default-alpn alpn=h2 no-default-alpn",
"1 . mandatory=key1,key2 alpn=h2 no-default-alpn",
"1 . mandatory=alpn,no-default-alpn key1=\\002h2 key2",
def test_svcb_alpn(self):
valid_inputs_two_items = (
- "1 . alpn=\"h2,h3\"",
+ '1 . alpn="h2,h3"',
"1 . alpn=h2,h3",
"1 . alpn=h\\050,h3",
- "1 . alpn=\"h\\050,h3\"",
+ '1 . alpn="h\\050,h3"',
"1 . alpn=\\h2,h3",
- "1 . alpn=\"h2\\,h3\"",
+ '1 . alpn="h2\\,h3"',
"1 . alpn=h2\\,h3",
"1 . alpn=h2\\044h3",
"1 . key1=\\002h2\\002h3",
self.check_valid_inputs(valid_inputs_two_items)
valid_inputs_one_item = (
- "1 . alpn=\"h2\\\\,h3\"",
+ '1 . alpn="h2\\\\,h3"',
"1 . alpn=h2\\\\,h3",
"1 . alpn=h2\\092\\044h3",
"1 . key1=\\005h2,h3",
"1 . alpn=",
"1 . alpn=h2,,h3",
"1 . alpn=01234567890abcdef01234567890abcdef01234567890abcdef"
- "01234567890abcdef01234567890abcdef01234567890abcdef"
- "01234567890abcdef01234567890abcdef01234567890abcdef"
- "01234567890abcdef01234567890abcdef01234567890abcdef"
- "01234567890abcdef01234567890abcdef01234567890abcdef"
- "01234567890abcdef",
- "1 . alpn=\",h2,h3\"",
- "1 . alpn=\"h2,h3,\"",
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef",
+ '1 . alpn=",h2,h3"',
+ '1 . alpn="h2,h3,"',
"1 . key1",
"1 . key1=",
"1 . key1=\\000",
def test_svcb_no_default_alpn(self):
valid_inputs = (
- "1 . alpn=\"h2\" no-default-alpn",
- "1 . alpn=\"h2\" no-default-alpn=\"\"",
- "1 . alpn=\"h2\" key2",
- "1 . alpn=\"h2\" key2=\"\"",
+ '1 . alpn="h2" no-default-alpn',
+ '1 . alpn="h2" no-default-alpn=""',
+ '1 . alpn="h2" key2',
+ '1 . alpn="h2" key2=""',
)
self.check_valid_inputs(valid_inputs)
invalid_inputs = (
"1 . no-default-alpn",
- "1 . no-default-alpn=\"\"",
+ '1 . no-default-alpn=""',
"1 . key2",
- "1 . key2=\"\"",
+ '1 . key2=""',
"1 . alpn=h2 no-default-alpn=foo",
"1 . alpn=h2 no-default-alpn=",
"1 . alpn=h2 key2=foo",
def test_svcb_port(self):
valid_inputs = (
- "1 . port=\"53\"",
+ '1 . port="53"',
"1 . port=53",
"1 . key3=\\000\\053",
)
def test_svcb_ipv4hint(self):
valid_inputs = (
- "1 . ipv4hint=\"0.0.0.0,1.1.1.1\"",
+ '1 . ipv4hint="0.0.0.0,1.1.1.1"',
"1 . ipv4hint=0.0.0.0,1.1.1.1",
"1 . key4=\\000\\000\\000\\000\\001\\001\\001\\001",
)
def test_svcb_ech(self):
valid_inputs = (
- "1 . ech=\"Zm9vMA==\"",
+ '1 . ech="Zm9vMA=="',
"1 . ech=Zm9vMA==",
"1 . key5=foo0",
"1 . key5=\\102\\111\\111\\048",
def test_svcb_ipv6hint(self):
valid_inputs = (
- "1 . ipv6hint=\"::4,1::\"",
+ '1 . ipv6hint="::4,1::"',
"1 . ipv6hint=::4,1::",
"1 . key6=\\000\\000\\000\\000\\000\\000\\000\\000"
- "\\000\\000\\000\\000\\000\\000\\000\\004"
- "\\000\\001\\000\\000\\000\\000\\000\\000"
- "\\000\\000\\000\\000\\000\\000\\000\\000",
+ "\\000\\000\\000\\000\\000\\000\\000\\004"
+ "\\000\\001\\000\\000\\000\\000\\000\\000"
+ "\\000\\000\\000\\000\\000\\000\\000\\000",
)
self.check_valid_inputs(valid_inputs)
def test_svcb_unknown(self):
valid_inputs_one_key = (
- "1 . key23=\"key45\"",
+ '1 . key23="key45"',
"1 . key23=key45",
"1 . key23=key\\052\\053",
- "1 . key23=\"key\\052\\053\"",
+ '1 . key23="key\\052\\053"',
"1 . key23=\\107\\101\\121\\052\\053",
)
self.check_valid_inputs(valid_inputs_one_key)
valid_inputs_one_key_empty = (
"1 . key23",
- "1 . key23=\"\"",
+ '1 . key23=""',
)
self.check_valid_inputs(valid_inputs_one_key_empty)
valid_inputs_two_keys = (
"1 . key24 key48",
- "1 . key24=\"\" key48",
+ '1 . key24="" key48',
)
self.check_valid_inputs(valid_inputs_two_keys)
def test_svcb_wire(self):
valid_inputs = (
- "1 . mandatory=\"alpn,port\" alpn=\"h2\" port=\"257\"",
+ '1 . mandatory="alpn,port" alpn="h2" port="257"',
"\\# 24 0001 00 0000000400010003 00010003026832 000300020101",
)
self.check_valid_inputs(valid_inputs)
- everything = \
- "100 foo.com. mandatory=\"alpn,port\" alpn=\"h2,h3\" " \
- " no-default-alpn port=\"12345\" ech=\"abcd\" " \
- " ipv4hint=1.2.3.4,4.3.2.1 ipv6hint=1::2,3::4" \
- " key12345=\"foo\""
- rr = dns.rdata.from_text('IN', 'SVCB', everything)
- rr2 = dns.rdata.from_text('IN', 'SVCB', rr.to_generic().to_text())
+ everything = (
+ '100 foo.com. mandatory="alpn,port" alpn="h2,h3" '
+ ' no-default-alpn port="12345" ech="abcd" '
+ " ipv4hint=1.2.3.4,4.3.2.1 ipv6hint=1::2,3::4"
+ ' key12345="foo"'
+ )
+ rr = dns.rdata.from_text("IN", "SVCB", everything)
+ rr2 = dns.rdata.from_text("IN", "SVCB", rr.to_generic().to_text())
self.assertEqual(rr, rr2)
invalid_inputs = (
self.check_invalid_inputs(invalid_inputs)
def test_misc_escape(self):
- rdata = dns.rdata.from_text('in', 'svcb', '1 . alpn=\\010\\010')
+ rdata = dns.rdata.from_text("in", "svcb", "1 . alpn=\\010\\010")
expected = '1 . alpn="\\\\010\\\\010"'
self.assertEqual(rdata.to_text(), expected)
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'svcb', '1 . alpn=\\0')
+ dns.rdata.from_text("in", "svcb", "1 . alpn=\\0")
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00')
+ dns.rdata.from_text("in", "svcb", "1 . alpn=\\00")
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00q')
+ dns.rdata.from_text("in", "svcb", "1 . alpn=\\00q")
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'svcb', '1 . alpn=\\256')
+ dns.rdata.from_text("in", "svcb", "1 . alpn=\\256")
# This doesn't usually get exercised, so we do it directly.
- gp = dns.rdtypes.svcbbase.GenericParam.from_value('\\001\\002')
+ gp = dns.rdtypes.svcbbase.GenericParam.from_value("\\001\\002")
expected = '"\\001\\002"'
self.assertEqual(gp.to_text(), expected)
self.assertTrue(text_token.is_identifier)
text_tokenizer.unget(text_token)
generic_tokenizer.unget(generic_token)
- text_rdata = dns.rdata.from_text('IN', 'SVCB', text_tokenizer)
- generic_rdata = dns.rdata.from_text('IN', 'SVCB', generic_tokenizer)
+ text_rdata = dns.rdata.from_text("IN", "SVCB", text_tokenizer)
+ generic_rdata = dns.rdata.from_text("IN", "SVCB", generic_tokenizer)
self.assertEqual(text_rdata, generic_rdata)
def test_svcb_spec_failure_cases(self):
# mandatory list (Section 7).
"1 foo.example.com. mandatory=key123,key123 key123=abc",
)
- self.check_invalid_inputs(failure_cases);
+ self.check_invalid_inputs(failure_cases)
def test_alias_mode(self):
- rd = dns.rdata.from_text('in', 'svcb', '0 .')
+ rd = dns.rdata.from_text("in", "svcb", "0 .")
self.assertEqual(len(rd.params), 0)
self.assertEqual(rd.target, dns.name.root)
- self.assertEqual(rd.to_text(), '0 .')
- rd = dns.rdata.from_text('in', 'svcb', '0 elsewhere.')
- self.assertEqual(rd.target, dns.name.from_text('elsewhere.'))
+ self.assertEqual(rd.to_text(), "0 .")
+ rd = dns.rdata.from_text("in", "svcb", "0 elsewhere.")
+ self.assertEqual(rd.target, dns.name.from_text("elsewhere."))
self.assertEqual(len(rd.params), 0)
# provoke 'parameters in AliasMode' from text.
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('in', 'svcb', '0 elsewhere. alpn=h2')
+ dns.rdata.from_text("in", "svcb", "0 elsewhere. alpn=h2")
# provoke 'parameters in AliasMode' from wire too.
- wire = bytes.fromhex('0000000000000400010003')
+ wire = bytes.fromhex("0000000000000400010003")
with self.assertRaises(dns.exception.FormError):
- dns.rdata.from_wire('in', 'svcb', wire, 0, len(wire))
+ dns.rdata.from_wire("in", "svcb", wire, 0, len(wire))
def test_immutability(self):
- alpn = dns.rdtypes.svcbbase.ALPNParam.from_value(['h2', 'h3'])
+ alpn = dns.rdtypes.svcbbase.ALPNParam.from_value(["h2", "h3"])
with self.assertRaises(TypeError):
- alpn.ids[0] = 'foo'
+ alpn.ids[0] = "foo"
with self.assertRaises(TypeError):
del alpn.ids[0]
with self.assertRaises(TypeError):
- alpn.ids = 'foo'
+ alpn.ids = "foo"
with self.assertRaises(TypeError):
del alpn.ids
def test_alias_not_compressed(self):
- rrs = dns.rrset.from_text('elsewhere.', 300, 'in', 'svcb',
- '0 elseWhere.')
+ rrs = dns.rrset.from_text("elsewhere.", 300, "in", "svcb", "0 elseWhere.")
output = io.BytesIO()
compress = {}
rrs.to_wire(output, compress)
wire = output.getvalue()
# Just one of these assertions is enough, but we do both to show
# the bug we're checking is fixed.
- assert not wire.endswith(b'\xc0\x00')
- assert wire.endswith(b'\x09elseWhere\x00')
+ assert not wire.endswith(b"\xc0\x00")
+ assert wire.endswith(b"\x09elseWhere\x00")
Token = dns.tokenizer.Token
-class TokenizerTestCase(unittest.TestCase):
+class TokenizerTestCase(unittest.TestCase):
def testStr(self):
- tok = dns.tokenizer.Tokenizer('foo')
+ tok = dns.tokenizer.Tokenizer("foo")
token = tok.get()
- self.assertEqual(token, Token(dns.tokenizer.IDENTIFIER, 'foo'))
+ self.assertEqual(token, Token(dns.tokenizer.IDENTIFIER, "foo"))
def testQuotedString1(self):
tok = dns.tokenizer.Tokenizer(r'"foo"')
token = tok.get()
- self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, 'foo'))
+ self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, "foo"))
def testQuotedString2(self):
tok = dns.tokenizer.Tokenizer(r'""')
token = tok.get()
- self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, ''))
+ self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, ""))
def testQuotedString3(self):
tok = dns.tokenizer.Tokenizer(r'"\"foo\""')
def testQuotedString4(self):
tok = dns.tokenizer.Tokenizer(r'"foo\010bar"')
token = tok.get()
- self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING,
- 'foo\\010bar'))
+ self.assertEqual(token, Token(dns.tokenizer.QUOTED_STRING, "foo\\010bar"))
def testQuotedString5(self):
with self.assertRaises(dns.exception.UnexpectedEnd):
tok.get()
def testEmpty1(self):
- tok = dns.tokenizer.Tokenizer('')
+ tok = dns.tokenizer.Tokenizer("")
token = tok.get()
self.assertTrue(token.is_eof())
def testEmpty2(self):
- tok = dns.tokenizer.Tokenizer('')
+ tok = dns.tokenizer.Tokenizer("")
token1 = tok.get()
token2 = tok.get()
self.assertTrue(token1.is_eof() and token2.is_eof())
def testEOL(self):
- tok = dns.tokenizer.Tokenizer('\n')
+ tok = dns.tokenizer.Tokenizer("\n")
token1 = tok.get()
token2 = tok.get()
self.assertTrue(token1.is_eol() and token2.is_eof())
def testWS1(self):
- tok = dns.tokenizer.Tokenizer(' \n')
+ tok = dns.tokenizer.Tokenizer(" \n")
token1 = tok.get()
self.assertTrue(token1.is_eol())
def testWS2(self):
- tok = dns.tokenizer.Tokenizer(' \n')
+ tok = dns.tokenizer.Tokenizer(" \n")
token1 = tok.get(want_leading=True)
self.assertTrue(token1.is_whitespace())
def testComment1(self):
- tok = dns.tokenizer.Tokenizer(' ;foo\n')
+ tok = dns.tokenizer.Tokenizer(" ;foo\n")
token1 = tok.get()
self.assertTrue(token1.is_eol())
def testComment2(self):
- tok = dns.tokenizer.Tokenizer(' ;foo\n')
+ tok = dns.tokenizer.Tokenizer(" ;foo\n")
token1 = tok.get(want_comment=True)
token2 = tok.get()
- self.assertEqual(token1, Token(dns.tokenizer.COMMENT, 'foo'))
+ self.assertEqual(token1, Token(dns.tokenizer.COMMENT, "foo"))
self.assertTrue(token2.is_eol())
def testComment3(self):
- tok = dns.tokenizer.Tokenizer(' ;foo bar\n')
+ tok = dns.tokenizer.Tokenizer(" ;foo bar\n")
token1 = tok.get(want_comment=True)
token2 = tok.get()
- self.assertEqual(token1, Token(dns.tokenizer.COMMENT, 'foo bar'))
+ self.assertEqual(token1, Token(dns.tokenizer.COMMENT, "foo bar"))
self.assertTrue(token2.is_eol())
def testMultiline1(self):
- tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)')
+ tok = dns.tokenizer.Tokenizer("( foo\n\n bar\n)")
tokens = list(iter(tok))
- self.assertEqual(tokens, [Token(dns.tokenizer.IDENTIFIER, 'foo'),
- Token(dns.tokenizer.IDENTIFIER, 'bar')])
+ self.assertEqual(
+ tokens,
+ [
+ Token(dns.tokenizer.IDENTIFIER, "foo"),
+ Token(dns.tokenizer.IDENTIFIER, "bar"),
+ ],
+ )
def testMultiline2(self):
- tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)\n')
+ tok = dns.tokenizer.Tokenizer("( foo\n\n bar\n)\n")
tokens = list(iter(tok))
- self.assertEqual(tokens, [Token(dns.tokenizer.IDENTIFIER, 'foo'),
- Token(dns.tokenizer.IDENTIFIER, 'bar'),
- Token(dns.tokenizer.EOL, '\n')])
+ self.assertEqual(
+ tokens,
+ [
+ Token(dns.tokenizer.IDENTIFIER, "foo"),
+ Token(dns.tokenizer.IDENTIFIER, "bar"),
+ Token(dns.tokenizer.EOL, "\n"),
+ ],
+ )
def testMultiline3(self):
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('foo)')
+ tok = dns.tokenizer.Tokenizer("foo)")
list(iter(tok))
def testMultiline4(self):
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('((foo)')
+ tok = dns.tokenizer.Tokenizer("((foo)")
list(iter(tok))
def testUnget1(self):
- tok = dns.tokenizer.Tokenizer('foo')
+ tok = dns.tokenizer.Tokenizer("foo")
t1 = tok.get()
tok.unget(t1)
t2 = tok.get()
self.assertEqual(t1, t2)
self.assertEqual(t1.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t1.value, 'foo')
+ self.assertEqual(t1.value, "foo")
def testUnget2(self):
with self.assertRaises(dns.tokenizer.UngetBufferFull):
- tok = dns.tokenizer.Tokenizer('foo')
+ tok = dns.tokenizer.Tokenizer("foo")
t1 = tok.get()
tok.unget(t1)
tok.unget(t1)
def testGetEOL1(self):
- tok = dns.tokenizer.Tokenizer('\n')
+ tok = dns.tokenizer.Tokenizer("\n")
t = tok.get_eol()
- self.assertEqual(t, '\n')
+ self.assertEqual(t, "\n")
def testGetEOL2(self):
- tok = dns.tokenizer.Tokenizer('')
+ tok = dns.tokenizer.Tokenizer("")
t = tok.get_eol()
- self.assertEqual(t, '')
+ self.assertEqual(t, "")
def testEscapedDelimiter1(self):
- tok = dns.tokenizer.Tokenizer(r'ch\ ld')
+ tok = dns.tokenizer.Tokenizer(r"ch\ ld")
t = tok.get()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, r'ch\ ld')
+ self.assertEqual(t.value, r"ch\ ld")
def testEscapedDelimiter2(self):
- tok = dns.tokenizer.Tokenizer(r'ch\032ld')
+ tok = dns.tokenizer.Tokenizer(r"ch\032ld")
t = tok.get()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, r'ch\032ld')
+ self.assertEqual(t.value, r"ch\032ld")
def testEscapedDelimiter3(self):
- tok = dns.tokenizer.Tokenizer(r'ch\ild')
+ tok = dns.tokenizer.Tokenizer(r"ch\ild")
t = tok.get()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, r'ch\ild')
+ self.assertEqual(t.value, r"ch\ild")
def testEscapedDelimiter1u(self):
- tok = dns.tokenizer.Tokenizer(r'ch\ ld')
+ tok = dns.tokenizer.Tokenizer(r"ch\ ld")
t = tok.get().unescape()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, r'ch ld')
+ self.assertEqual(t.value, r"ch ld")
def testEscapedDelimiter2u(self):
- tok = dns.tokenizer.Tokenizer(r'ch\032ld')
+ tok = dns.tokenizer.Tokenizer(r"ch\032ld")
t = tok.get().unescape()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, 'ch ld')
+ self.assertEqual(t.value, "ch ld")
def testEscapedDelimiter3u(self):
- tok = dns.tokenizer.Tokenizer(r'ch\ild')
+ tok = dns.tokenizer.Tokenizer(r"ch\ild")
t = tok.get().unescape()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, r'child')
+ self.assertEqual(t.value, r"child")
def testGetUInt(self):
- tok = dns.tokenizer.Tokenizer('1234')
+ tok = dns.tokenizer.Tokenizer("1234")
v = tok.get_int()
self.assertEqual(v, 1234)
with self.assertRaises(dns.exception.SyntaxError):
tok = dns.tokenizer.Tokenizer('"1234"')
tok.get_int()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('q1234')
+ tok = dns.tokenizer.Tokenizer("q1234")
tok.get_int()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('281474976710656')
+ tok = dns.tokenizer.Tokenizer("281474976710656")
tok.get_uint48()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('4294967296')
+ tok = dns.tokenizer.Tokenizer("4294967296")
tok.get_uint32()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('65536')
+ tok = dns.tokenizer.Tokenizer("65536")
tok.get_uint16()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('256')
+ tok = dns.tokenizer.Tokenizer("256")
tok.get_uint8()
# Even though it is badly named get_int(), it's really get_unit!
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('-1234')
+ tok = dns.tokenizer.Tokenizer("-1234")
tok.get_int()
# get_uint16 can do other bases too, and has a custom error
# for base 8.
- tok = dns.tokenizer.Tokenizer('177777')
+ tok = dns.tokenizer.Tokenizer("177777")
self.assertEqual(tok.get_uint16(base=8), 65535)
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('200000')
+ tok = dns.tokenizer.Tokenizer("200000")
tok.get_uint16(base=8)
def testGetString(self):
- tok = dns.tokenizer.Tokenizer('foo')
+ tok = dns.tokenizer.Tokenizer("foo")
v = tok.get_string()
- self.assertEqual(v, 'foo')
+ self.assertEqual(v, "foo")
tok = dns.tokenizer.Tokenizer('"foo"')
v = tok.get_string()
- self.assertEqual(v, 'foo')
- tok = dns.tokenizer.Tokenizer('abcdefghij')
+ self.assertEqual(v, "foo")
+ tok = dns.tokenizer.Tokenizer("abcdefghij")
v = tok.get_string(max_length=10)
- self.assertEqual(v, 'abcdefghij')
+ self.assertEqual(v, "abcdefghij")
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('abcdefghij')
+ tok = dns.tokenizer.Tokenizer("abcdefghij")
tok.get_string(max_length=9)
- tok = dns.tokenizer.Tokenizer('')
+ tok = dns.tokenizer.Tokenizer("")
with self.assertRaises(dns.exception.SyntaxError):
tok.get_string()
def testMultiLineWithComment(self):
- tok = dns.tokenizer.Tokenizer('( ; abc\n)')
+ tok = dns.tokenizer.Tokenizer("( ; abc\n)")
tok.get_eol()
# Nothing to assert here, as we're testing tok.get_eol() does NOT
# raise.
def testEOLAfterComment(self):
- tok = dns.tokenizer.Tokenizer('; abc\n')
+ tok = dns.tokenizer.Tokenizer("; abc\n")
t = tok.get()
self.assertTrue(t.is_eol())
def testEOFAfterComment(self):
- tok = dns.tokenizer.Tokenizer('; abc')
+ tok = dns.tokenizer.Tokenizer("; abc")
t = tok.get()
self.assertTrue(t.is_eof())
def testMultiLineWithEOFAfterComment(self):
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('( ; abc')
+ tok = dns.tokenizer.Tokenizer("( ; abc")
tok.get_eol()
def testEscapeUnexpectedEnd(self):
with self.assertRaises(dns.exception.UnexpectedEnd):
- tok = dns.tokenizer.Tokenizer('\\')
+ tok = dns.tokenizer.Tokenizer("\\")
tok.get()
def testEscapeBounds(self):
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('\\256')
+ tok = dns.tokenizer.Tokenizer("\\256")
tok.get().unescape()
with self.assertRaises(dns.exception.SyntaxError):
- tok = dns.tokenizer.Tokenizer('\\256')
+ tok = dns.tokenizer.Tokenizer("\\256")
tok.get().unescape_to_bytes()
def testGetUngetRegetComment(self):
- tok = dns.tokenizer.Tokenizer(';comment')
+ tok = dns.tokenizer.Tokenizer(";comment")
t1 = tok.get(want_comment=True)
tok.unget(t1)
t2 = tok.get(want_comment=True)
tok.get().unescape_to_bytes()
def testTokenMisc(self):
- t1 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'hi')
- t2 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'hi')
- t3 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, 'there')
+ t1 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "hi")
+ t2 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "hi")
+ t3 = dns.tokenizer.Token(dns.tokenizer.IDENTIFIER, "there")
self.assertEqual(t1, t2)
- self.assertFalse(t1 == 'hi') # not NotEqual because we want to use ==
- self.assertNotEqual(t1, 'hi')
+ self.assertFalse(t1 == "hi") # not NotEqual because we want to use ==
+ self.assertNotEqual(t1, "hi")
self.assertNotEqual(t1, t3)
self.assertEqual(str(t1), '3 "hi"')
def testStdinFilename(self):
tok = dns.tokenizer.Tokenizer()
- self.assertEqual(tok.filename, '<stdin>')
+ self.assertEqual(tok.filename, "<stdin>")
def testBytesLiteral(self):
- tok = dns.tokenizer.Tokenizer(b'this is input')
- self.assertEqual(tok.get().value, 'this')
- self.assertEqual(tok.filename, '<string>')
- tok = dns.tokenizer.Tokenizer(b'this is input', 'myfilename')
- self.assertEqual(tok.filename, 'myfilename')
+ tok = dns.tokenizer.Tokenizer(b"this is input")
+ self.assertEqual(tok.get().value, "this")
+ self.assertEqual(tok.filename, "<string>")
+ tok = dns.tokenizer.Tokenizer(b"this is input", "myfilename")
+ self.assertEqual(tok.filename, "myfilename")
def testUngetBranches(self):
- tok = dns.tokenizer.Tokenizer(b' this is input')
+ tok = dns.tokenizer.Tokenizer(b" this is input")
t = tok.get(want_leading=True)
tok.unget(t)
t = tok.get(want_leading=True)
tok.unget(t)
t = tok.get()
self.assertEqual(t.ttype, dns.tokenizer.IDENTIFIER)
- self.assertEqual(t.value, 'this')
- tok = dns.tokenizer.Tokenizer(b'; this is input\n')
+ self.assertEqual(t.value, "this")
+ tok = dns.tokenizer.Tokenizer(b"; this is input\n")
t = tok.get(want_comment=True)
tok.unget(t)
t = tok.get(want_comment=True)
t = tok.get()
self.assertEqual(t.ttype, dns.tokenizer.EOL)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
return Transaction(self, replacement, False)
def origin_information(self):
- return (dns.name.from_text('example'), True, dns.name.empty)
+ return (dns.name.from_text("example"), True, dns.name.empty)
def get_class(self):
return dns.rdataclass.IN
def _set_origin(self, origin):
pass
+
@pytest.fixture
def db():
db = DB()
- rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'content')
+ rrset = dns.rrset.from_text("content", 300, "in", "txt", "content")
db.rdatasets[(rrset.name, rrset.rdtype, 0)] = rrset
return db
+
def test_basic(db):
# successful txn
with db.writer() as txn:
- rrset = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.1', '10.0.0.2')
+ rrset = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1", "10.0.0.2")
txn.add(rrset)
assert txn.name_exists(rrset.name)
- assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \
- rrset
+ assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == rrset
# rollback
with pytest.raises(Exception):
with db.writer() as txn:
- rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.3', '10.0.0.4')
+ rrset2 = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.3", "10.0.0.4")
txn.add(rrset2)
raise Exception()
- assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \
- rrset
+ assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == rrset
with db.writer() as txn:
txn.delete(rrset.name)
- assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) \
- is None
+ assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) is None
+
def test_get(db):
with db.writer() as txn:
- content = dns.name.from_text('content', None)
+ content = dns.name.from_text("content", None)
rdataset = txn.get(content, dns.rdatatype.TXT)
assert rdataset is not None
- assert rdataset[0].strings == (b'content',)
+ assert rdataset[0].strings == (b"content",)
assert isinstance(rdataset, dns.rdataset.ImmutableRdataset)
+
def test_add(db):
with db.writer() as txn:
- rrset = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.1', '10.0.0.2')
+ rrset = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1", "10.0.0.2")
txn.add(rrset)
- rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.3', '10.0.0.4')
+ rrset2 = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.3", "10.0.0.4")
txn.add(rrset2)
- expected = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.1', '10.0.0.2',
- '10.0.0.3', '10.0.0.4')
- assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \
- expected
+ expected = dns.rrset.from_text(
+ "foo", 300, "in", "a", "10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4"
+ )
+ assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == expected
+
def test_replacement(db):
with db.writer() as txn:
- rrset = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.1', '10.0.0.2')
+ rrset = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1", "10.0.0.2")
txn.add(rrset)
- rrset2 = dns.rrset.from_text('foo', 300, 'in', 'a',
- '10.0.0.3', '10.0.0.4')
+ rrset2 = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.3", "10.0.0.4")
txn.replace(rrset2)
- assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == \
- rrset2
+ assert db.rdatasets[(rrset.name, rrset.rdtype, 0)] == rrset2
+
def test_delete(db):
with db.writer() as txn:
- txn.delete(dns.name.from_text('nonexistent', None))
- content = dns.name.from_text('content', None)
- content2 = dns.name.from_text('content2', None)
+ txn.delete(dns.name.from_text("nonexistent", None))
+ content = dns.name.from_text("content", None)
+ content2 = dns.name.from_text("content2", None)
txn.delete(content)
assert not txn.name_exists(content)
txn.delete(content2, dns.rdatatype.TXT)
- rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'new-content')
+ rrset = dns.rrset.from_text("content", 300, "in", "txt", "new-content")
txn.add(rrset)
assert txn.name_exists(content)
txn.delete(content, dns.rdatatype.TXT)
assert not txn.name_exists(content)
- rrset = dns.rrset.from_text('content2', 300, 'in', 'txt', 'new-content')
+ rrset = dns.rrset.from_text("content2", 300, "in", "txt", "new-content")
txn.delete(rrset)
content_keys = [k for k in db.rdatasets if k[0] == content]
assert len(content_keys) == 0
+
def test_delete_exact(db):
with db.writer() as txn:
- rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'bad-content')
+ rrset = dns.rrset.from_text("content", 300, "in", "txt", "bad-content")
with pytest.raises(dns.transaction.DeleteNotExact):
txn.delete_exact(rrset)
- rrset = dns.rrset.from_text('content2', 300, 'in', 'txt', 'bad-content')
+ rrset = dns.rrset.from_text("content2", 300, "in", "txt", "bad-content")
with pytest.raises(dns.transaction.DeleteNotExact):
txn.delete_exact(rrset)
with pytest.raises(dns.transaction.DeleteNotExact):
txn.delete_exact(rrset.name)
with pytest.raises(dns.transaction.DeleteNotExact):
txn.delete_exact(rrset.name, dns.rdatatype.TXT)
- rrset = dns.rrset.from_text('content', 300, 'in', 'txt', 'content')
+ rrset = dns.rrset.from_text("content", 300, "in", "txt", "content")
txn.delete_exact(rrset)
- assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) \
- is None
+ assert db.rdatasets.get((rrset.name, rrset.rdtype, 0)) is None
+
def test_parameter_forms(db):
with db.writer() as txn:
- foo = dns.name.from_text('foo', None)
- rdataset = dns.rdataset.from_text('in', 'a', 300,
- '10.0.0.1', '10.0.0.2')
- rdata1 = dns.rdata.from_text('in', 'a', '10.0.0.3')
- rdata2 = dns.rdata.from_text('in', 'a', '10.0.0.4')
+ foo = dns.name.from_text("foo", None)
+ rdataset = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ rdata1 = dns.rdata.from_text("in", "a", "10.0.0.3")
+ rdata2 = dns.rdata.from_text("in", "a", "10.0.0.4")
txn.add(foo, rdataset)
txn.add(foo, 100, rdata1)
txn.add(foo, 30, rdata2)
- expected = dns.rrset.from_text('foo', 30, 'in', 'a',
- '10.0.0.1', '10.0.0.2',
- '10.0.0.3', '10.0.0.4')
- assert db.rdatasets[(foo, rdataset.rdtype, 0)] == \
- expected
+ expected = dns.rrset.from_text(
+ "foo", 30, "in", "a", "10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4"
+ )
+ assert db.rdatasets[(foo, rdataset.rdtype, 0)] == expected
with db.writer() as txn:
txn.delete(foo, rdataset)
txn.delete(foo, rdata1)
txn.delete(foo, rdata2)
- assert db.rdatasets.get((foo, rdataset.rdtype, 0)) \
- is None
+ assert db.rdatasets.get((foo, rdataset.rdtype, 0)) is None
+
def test_bad_parameters(db):
with db.writer() as txn:
with pytest.raises(TypeError):
txn.add(1)
with pytest.raises(TypeError):
- rrset = dns.rrset.from_text('bar', 300, 'in', 'txt', 'bar')
+ rrset = dns.rrset.from_text("bar", 300, "in", "txt", "bar")
txn.add(rrset, 1)
with pytest.raises(ValueError):
- foo = dns.name.from_text('foo', None)
- rdata = dns.rdata.from_text('in', 'a', '10.0.0.3')
+ foo = dns.name.from_text("foo", None)
+ rdata = dns.rdata.from_text("in", "a", "10.0.0.3")
txn.add(foo, 0x100000000, rdata)
with pytest.raises(TypeError):
txn.add(foo)
with pytest.raises(TypeError):
txn.add(foo, 300)
with pytest.raises(TypeError):
- txn.add(foo, 300, 'hi')
+ txn.add(foo, 300, "hi")
with pytest.raises(TypeError):
- txn.add(foo, 'hi')
+ txn.add(foo, "hi")
with pytest.raises(TypeError):
txn.delete()
with pytest.raises(TypeError):
txn.delete(1)
+
def test_cannot_store_non_origin_soa(db):
with pytest.raises(ValueError):
with db.writer() as txn:
- rrset = dns.rrset.from_text('foo', 300, 'in', 'SOA',
- '. . 1 2 3 4 5')
+ rrset = dns.rrset.from_text("foo", 300, "in", "SOA", ". . 1 2 3 4 5")
txn.add(rrset)
+
example_text = """$TTL 3600
$ORIGIN example.
@ soa foo bar 1 2 3 4 5
ns3 3600 IN A 10.0.0.3
"""
+
@pytest.fixture(params=[dns.zone.Zone, dns.versioned.Zone])
def zone(request):
return dns.zone.from_text(example_text, zone_factory=request.param)
+
def test_zone_basic(zone):
with zone.writer() as txn:
- txn.delete(dns.name.from_text('bar.foo', None))
- rd = dns.rdata.from_text('in', 'ns', 'ns3')
+ txn.delete(dns.name.from_text("bar.foo", None))
+ rd = dns.rdata.from_text("in", "ns", "ns3")
txn.add(dns.name.empty, 3600, rd)
- rd = dns.rdata.from_text('in', 'a', '10.0.0.3')
- txn.add(dns.name.from_text('ns3', None), 3600, rd)
+ rd = dns.rdata.from_text("in", "a", "10.0.0.3")
+ txn.add(dns.name.from_text("ns3", None), 3600, rd)
output = zone.to_text()
assert output == example_text_output
+
def test_explicit_rollback_and_commit(zone):
with zone.writer() as txn:
assert not txn.changed()
- txn.delete(dns.name.from_text('bar.foo', None))
+ txn.delete(dns.name.from_text("bar.foo", None))
txn.rollback()
- assert zone.get_node('bar.foo') is not None
+ assert zone.get_node("bar.foo") is not None
with zone.writer() as txn:
assert not txn.changed()
- txn.delete(dns.name.from_text('bar.foo', None))
+ txn.delete(dns.name.from_text("bar.foo", None))
txn.commit()
- assert zone.get_node('bar.foo') is None
+ assert zone.get_node("bar.foo") is None
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
- txn.delete(dns.name.from_text('bar.foo', None))
+ txn.delete(dns.name.from_text("bar.foo", None))
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
- txn.add('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi'))
+ txn.add("bar.foo", 300, dns.rdata.from_text("in", "txt", "hi"))
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
- txn.replace('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi'))
+ txn.replace("bar.foo", 300, dns.rdata.from_text("in", "txt", "hi"))
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.reader() as txn:
txn.rollback()
- txn.get('bar.foo', 'in', 'mx')
+ txn.get("bar.foo", "in", "mx")
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
- txn.delete_exact('bar.foo')
+ txn.delete_exact("bar.foo")
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
- txn.name_exists('bar.foo')
+ txn.name_exists("bar.foo")
with pytest.raises(dns.transaction.AlreadyEnded):
with zone.writer() as txn:
txn.rollback()
for rdataset in txn:
pass
+
def test_zone_changed(zone):
# Read-only is not changed!
with zone.reader() as txn:
# delete an existing name
with zone.writer() as txn:
assert not txn.changed()
- txn.delete(dns.name.from_text('bar.foo', None))
+ txn.delete(dns.name.from_text("bar.foo", None))
assert txn.changed()
# delete a nonexistent name
with zone.writer() as txn:
assert not txn.changed()
- txn.delete(dns.name.from_text('unknown.bar.foo', None))
+ txn.delete(dns.name.from_text("unknown.bar.foo", None))
assert not txn.changed()
# delete a nonexistent rdataset from an extant node
with zone.writer() as txn:
assert not txn.changed()
- txn.delete(dns.name.from_text('bar.foo', None), 'txt')
+ txn.delete(dns.name.from_text("bar.foo", None), "txt")
assert not txn.changed()
# add an rdataset to an extant Node
with zone.writer() as txn:
assert not txn.changed()
- txn.add('bar.foo', 300, dns.rdata.from_text('in', 'txt', 'hi'))
+ txn.add("bar.foo", 300, dns.rdata.from_text("in", "txt", "hi"))
assert txn.changed()
# add an rdataset to a nonexistent Node
with zone.writer() as txn:
assert not txn.changed()
- txn.add('foo.foo', 300, dns.rdata.from_text('in', 'txt', 'hi'))
+ txn.add("foo.foo", 300, dns.rdata.from_text("in", "txt", "hi"))
assert txn.changed()
+
def test_zone_base_layer(zone):
with zone.writer() as txn:
# Get a set from the zone layer
rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE)
- expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2')
+ expected = dns.rdataset.from_text("in", "ns", 300, "ns1", "ns2")
assert rdataset == expected
+
def test_zone_transaction_layer(zone):
with zone.writer() as txn:
# Make a change
- rd = dns.rdata.from_text('in', 'ns', 'ns3')
+ rd = dns.rdata.from_text("in", "ns", "ns3")
txn.add(dns.name.empty, 3600, rd)
# Get a set from the transaction layer
- expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2', 'ns3')
+ expected = dns.rdataset.from_text("in", "ns", 300, "ns1", "ns2", "ns3")
rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE)
assert rdataset == expected
assert txn.name_exists(dns.name.empty)
- ns1 = dns.name.from_text('ns1', None)
+ ns1 = dns.name.from_text("ns1", None)
assert txn.name_exists(ns1)
- ns99 = dns.name.from_text('ns99', None)
+ ns99 = dns.name.from_text("ns99", None)
assert not txn.name_exists(ns99)
+
def test_zone_add_and_delete(zone):
with zone.writer() as txn:
- a99 = dns.name.from_text('a99', None)
- a100 = dns.name.from_text('a100', None)
- a101 = dns.name.from_text('a101', None)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99')
+ a99 = dns.name.from_text("a99", None)
+ a100 = dns.name.from_text("a100", None)
+ a101 = dns.name.from_text("a101", None)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.99")
txn.add(a99, rds)
txn.delete(a99, dns.rdatatype.A)
txn.delete(a100, dns.rdatatype.A)
assert not txn.name_exists(a99)
assert not txn.name_exists(a100)
assert not txn.name_exists(a101)
- ns1 = dns.name.from_text('ns1', None)
+ ns1 = dns.name.from_text("ns1", None)
txn.delete(ns1, dns.rdatatype.A)
assert not txn.name_exists(ns1)
with zone.writer() as txn:
assert not txn.name_exists(a99)
assert txn.name_exists(a100)
+
def test_write_after_rollback(zone):
with pytest.raises(ExpectedException):
with zone.writer() as txn:
- a99 = dns.name.from_text('a99', None)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99')
+ a99 = dns.name.from_text("a99", None)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.99")
txn.add(a99, rds)
raise ExpectedException
with zone.writer() as txn:
- a99 = dns.name.from_text('a99', None)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.99.99.99')
+ a99 = dns.name.from_text("a99", None)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.99.99.99")
txn.add(a99, rds)
- assert zone.get_rdataset('a99', 'a') == rds
+ assert zone.get_rdataset("a99", "a") == rds
+
def test_zone_get_deleted(zone):
with zone.writer() as txn:
- ns1 = dns.name.from_text('ns1', None)
+ ns1 = dns.name.from_text("ns1", None)
assert txn.get(ns1, dns.rdatatype.A) is not None
txn.delete(ns1)
assert txn.get(ns1, dns.rdatatype.A) is None
- ns2 = dns.name.from_text('ns2', None)
+ ns2 = dns.name.from_text("ns2", None)
txn.delete(ns2, dns.rdatatype.A)
assert txn.get(ns2, dns.rdatatype.A) is None
+
def test_zone_bad_class(zone):
with zone.writer() as txn:
- rds = dns.rdataset.from_text('ch', 'ns', 300, 'ns1', 'ns2')
+ rds = dns.rdataset.from_text("ch", "ns", 300, "ns1", "ns2")
with pytest.raises(ValueError):
txn.add(dns.name.empty, rds)
with pytest.raises(ValueError):
with pytest.raises(ValueError):
txn.delete(dns.name.empty, rds)
+
def test_update_serial(zone):
# basic
with zone.writer() as txn:
txn.update_serial()
- rdataset = zone.find_rdataset('@', 'soa')
+ rdataset = zone.find_rdataset("@", "soa")
assert rdataset[0].serial == 2
# max
with zone.writer() as txn:
- txn.update_serial(0xffffffff, False)
- rdataset = zone.find_rdataset('@', 'soa')
- assert rdataset[0].serial == 0xffffffff
+ txn.update_serial(0xFFFFFFFF, False)
+ rdataset = zone.find_rdataset("@", "soa")
+ assert rdataset[0].serial == 0xFFFFFFFF
# wraparound to 1
with zone.writer() as txn:
txn.update_serial()
- rdataset = zone.find_rdataset('@', 'soa')
+ rdataset = zone.find_rdataset("@", "soa")
assert rdataset[0].serial == 1
# trying to set to zero sets to 1
with zone.writer() as txn:
txn.update_serial(0, False)
- rdataset = zone.find_rdataset('@', 'soa')
+ rdataset = zone.find_rdataset("@", "soa")
assert rdataset[0].serial == 1
with pytest.raises(KeyError):
with zone.writer() as txn:
- txn.update_serial(name=dns.name.from_text('unknown', None))
+ txn.update_serial(name=dns.name.from_text("unknown", None))
with pytest.raises(ValueError):
with zone.writer() as txn:
txn.update_serial(-1)
with zone.writer() as txn:
txn.update_serial(2**31)
+
class ExpectedException(Exception):
pass
+
def test_zone_rollback(zone):
- a99 = dns.name.from_text('a99.example.')
+ a99 = dns.name.from_text("a99.example.")
try:
with zone.writer() as txn:
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99')
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.99")
txn.add(a99, rds)
assert txn.name_exists(a99)
raise ExpectedException
pass
assert not zone.get_node(a99)
+
def test_zone_ooz_name(zone):
with zone.writer() as txn:
with pytest.raises(KeyError):
- a99 = dns.name.from_text('a99.not-example.')
+ a99 = dns.name.from_text("a99.not-example.")
assert txn.name_exists(a99)
+
def test_zone_iteration(zone):
expected = {}
for (name, rdataset) in zone.iterate_rdatasets():
actual[(name, rdataset.rdtype, rdataset.covers)] = rdataset
assert actual == expected
+
def test_iteration_in_replacement_txn(zone):
- rds = dns.rdataset.from_text('in', 'a', 300, '1.2.3.4', '5.6.7.8')
+ rds = dns.rdataset.from_text("in", "a", 300, "1.2.3.4", "5.6.7.8")
expected = {}
expected[(dns.name.empty, rds.rdtype, rds.covers)] = rds
with zone.writer(True) as txn:
actual[(name, rdataset.rdtype, rdataset.covers)] = rdataset
assert actual == expected
+
def test_replacement_commit(zone):
- rds = dns.rdataset.from_text('in', 'a', 300, '1.2.3.4', '5.6.7.8')
+ rds = dns.rdataset.from_text("in", "a", 300, "1.2.3.4", "5.6.7.8")
expected = {}
expected[(dns.name.empty, rds.rdtype, rds.covers)] = rds
with zone.writer(True) as txn:
actual[(name, rdataset.rdtype, rdataset.covers)] = rdataset
assert actual == expected
+
def test_replacement_get(zone):
with zone.writer(True) as txn:
- rds = txn.get(dns.name.empty, 'soa')
+ rds = txn.get(dns.name.empty, "soa")
assert rds is None
def vzone():
return dns.zone.from_text(example_text, zone_factory=dns.versioned.Zone)
+
def test_vzone_read_only(vzone):
with vzone.reader() as txn:
rdataset = txn.get(dns.name.empty, dns.rdatatype.NS, dns.rdatatype.NONE)
- expected = dns.rdataset.from_text('in', 'ns', 300, 'ns1', 'ns2')
+ expected = dns.rdataset.from_text("in", "ns", 300, "ns1", "ns2")
assert rdataset == expected
with pytest.raises(dns.transaction.ReadOnly):
txn.replace(dns.name.empty, expected)
+
def test_vzone_multiple_versions(vzone):
assert len(vzone._versions) == 1
vzone.set_max_versions(None) # unlimited!
txn.update_serial()
with vzone.writer() as txn:
txn.update_serial(1000, False)
- rdataset = vzone.find_rdataset('@', 'soa')
+ rdataset = vzone.find_rdataset("@", "soa")
assert rdataset[0].serial == 1000
assert len(vzone._versions) == 4
with vzone.reader(id=5) as txn:
assert txn.version.id == 5
- rdataset = txn.get('@', 'soa')
+ rdataset = txn.get("@", "soa")
assert rdataset[0].serial == 1000
with vzone.reader(serial=1000) as txn:
assert txn.version.id == 5
- rdataset = txn.get('@', 'soa')
+ rdataset = txn.get("@", "soa")
assert rdataset[0].serial == 1000
vzone.set_max_versions(2)
assert len(vzone._versions) == 2
# The ones that survived should be 3 and 1000
- rdataset = vzone._versions[0].get_rdataset(dns.name.empty,
- dns.rdatatype.SOA,
- dns.rdatatype.NONE)
+ rdataset = vzone._versions[0].get_rdataset(
+ dns.name.empty, dns.rdatatype.SOA, dns.rdatatype.NONE
+ )
assert rdataset[0].serial == 3
- rdataset = vzone._versions[1].get_rdataset(dns.name.empty,
- dns.rdatatype.SOA,
- dns.rdatatype.NONE)
+ rdataset = vzone._versions[1].get_rdataset(
+ dns.name.empty, dns.rdatatype.SOA, dns.rdatatype.NONE
+ )
assert rdataset[0].serial == 1000
with pytest.raises(ValueError):
vzone.set_max_versions(0)
+
# for debugging if needed
def _dump(zone):
for v in zone._versions:
- print('VERSION', v.id)
+ print("VERSION", v.id)
for (name, n) in v.nodes.items():
for rdataset in n:
print(rdataset.to_text(name))
+
def test_vzone_open_txn_pins_versions(vzone):
assert len(vzone._versions) == 1
vzone.set_max_versions(None) # unlimited!
with vzone.reader(id=2) as txn:
vzone.set_max_versions(1)
with vzone.reader(id=3) as txn:
- rdataset = txn.get('@', 'soa')
+ rdataset = txn.get("@", "soa")
assert rdataset[0].serial == 2
assert len(vzone._versions) == 4
assert len(vzone._versions) == 1
- rdataset = vzone.find_rdataset('@', 'soa')
+ rdataset = vzone.find_rdataset("@", "soa")
assert vzone._versions[0].id == 5
assert rdataset[0].serial == 4
# wait until two blocks
while len(zone._write_waiters) == 0:
time.sleep(0.01)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.98')
- txn.add('a98', rds)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.98")
+ txn.add("a98", rds)
def run_two(zone):
# wait until one has the lock so we know we will block if we
# get the call done before the sleep in one completes
one_got_lock.wait()
with zone.writer() as txn:
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.99')
- txn.add('a99', rds)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.99")
+ txn.add("a99", rds)
def test_vzone_concurrency(vzone):
t1 = threading.Thread(target=run_one, args=(vzone,))
t1.join()
t2.join()
with vzone.reader() as txn:
- assert txn.name_exists('a98')
- assert txn.name_exists('a99')
+ assert txn.name_exists("a98")
+ assert txn.name_exists("a99")
except ImportError: # pragma: no cover
pass
import dns.message
import dns.rdtypes.ANY.TKEY
-keyring = dns.tsigkeyring.from_text(
- {
- 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
- }
-)
+keyring = dns.tsigkeyring.from_text({"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="})
-keyname = dns.name.from_text('keyname')
+keyname = dns.name.from_text("keyname")
class TSIGTestCase(unittest.TestCase):
-
def test_get_context(self):
- key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha256')
+ key = dns.tsig.Key("foo.com", "abcd", "hmac-sha256")
ctx = dns.tsig.get_context(key)
- self.assertEqual(ctx.name, 'hmac-sha256')
- key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512')
+ self.assertEqual(ctx.name, "hmac-sha256")
+ key = dns.tsig.Key("foo.com", "abcd", "hmac-sha512")
ctx = dns.tsig.get_context(key)
- self.assertEqual(ctx.name, 'hmac-sha512')
- bogus = dns.tsig.Key('foo.com', 'abcd', 'bogus')
+ self.assertEqual(ctx.name, "hmac-sha512")
+ bogus = dns.tsig.Key("foo.com", "abcd", "bogus")
with self.assertRaises(NotImplementedError):
dns.tsig.get_context(bogus)
def test_tsig_message_properties(self):
- m = dns.message.make_query('example', 'a')
+ m = dns.message.make_query("example", "a")
self.assertIsNone(m.keyname)
self.assertIsNone(m.keyalgorithm)
self.assertIsNone(m.tsig_error)
self.assertEqual(m.keyname, keyname)
self.assertEqual(m.keyalgorithm, dns.tsig.default_algorithm)
self.assertEqual(m.tsig_error, dns.rcode.NOERROR)
- m = dns.message.make_query('example', 'a')
+ m = dns.message.make_query("example", "a")
m.use_tsig(keyring, keyname, tsig_error=dns.rcode.BADKEY)
self.assertEqual(m.tsig_error, dns.rcode.BADKEY)
def test_verify_mac_for_context(self):
- key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512')
+ key = dns.tsig.Key("foo.com", "abcd", "hmac-sha512")
ctx = dns.tsig.get_context(key)
- bad_expected = b'xxxxxxxxxx'
+ bad_expected = b"xxxxxxxxxx"
with self.assertRaises(dns.tsig.BadSignature):
ctx.verify(bad_expected)
def test_validate(self):
# make message and grab the TSIG
- m = dns.message.make_query('example', 'a')
+ m = dns.message.make_query("example", "a")
m.use_tsig(keyring, keyname, algorithm=dns.tsig.HMAC_SHA256)
w = m.to_wire()
tsig = m.tsig[0]
# get the time and create a key with matching characteristics
now = int(time.time())
- key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha256')
+ key = dns.tsig.Key("foo.com", "abcd", "hmac-sha256")
# add enough to the time to take it over the fudge amount
with self.assertRaises(dns.tsig.BadTime):
- dns.tsig.validate(w, key, dns.name.from_text('foo.com'),
- tsig, now + 1000, b'', 0)
+ dns.tsig.validate(
+ w, key, dns.name.from_text("foo.com"), tsig, now + 1000, b"", 0
+ )
# change the key name
with self.assertRaises(dns.tsig.BadKey):
- dns.tsig.validate(w, key, dns.name.from_text('bar.com'),
- tsig, now, b'', 0)
+ dns.tsig.validate(w, key, dns.name.from_text("bar.com"), tsig, now, b"", 0)
# change the key algorithm
- key = dns.tsig.Key('foo.com', 'abcd', 'hmac-sha512')
+ key = dns.tsig.Key("foo.com", "abcd", "hmac-sha512")
with self.assertRaises(dns.tsig.BadAlgorithm):
- dns.tsig.validate(w, key, dns.name.from_text('foo.com'),
- tsig, now, b'', 0)
+ dns.tsig.validate(w, key, dns.name.from_text("foo.com"), tsig, now, b"", 0)
def test_gssapi_context(self):
def verify_signature(data, mac):
- if data == b'throw':
+ if data == b"throw":
raise Exception
return None
# mock out the gssapi context to return some dummy values
gssapi_context_mock = Mock()
- gssapi_context_mock.get_signature.return_value = b'xxxxxxxxxxx'
+ gssapi_context_mock.get_signature.return_value = b"xxxxxxxxxxx"
gssapi_context_mock.verify_signature.side_effect = verify_signature
# create the key and add it to the keyring
- keyname = 'gsstsigtest'
- key = dns.tsig.Key(keyname, gssapi_context_mock, 'gss-tsig')
+ keyname = "gsstsigtest"
+ key = dns.tsig.Key(keyname, gssapi_context_mock, "gss-tsig")
ctx = dns.tsig.get_context(key)
- self.assertEqual(ctx.name, 'gss-tsig')
+ self.assertEqual(ctx.name, "gss-tsig")
gsskeyname = dns.name.from_text(keyname)
keyring[gsskeyname] = key
# make sure we can get the keyring (no exception == success)
text = dns.tsigkeyring.to_text(keyring)
- self.assertNotEqual(text, '')
+ self.assertNotEqual(text, "")
# test exceptional case for _verify_mac_for_context
with self.assertRaises(dns.tsig.BadSignature):
- ctx.update(b'throw')
- ctx.verify(b'bogus')
+ ctx.update(b"throw")
+ ctx.verify(b"bogus")
gssapi_context_mock.verify_signature.assert_called()
self.assertEqual(gssapi_context_mock.verify_signature.call_count, 1)
# simulate case where TKEY message is used to establish the context;
# first, the query from the client
- tkey_message = dns.message.make_query(keyname, 'tkey', 'any')
+ tkey_message = dns.message.make_query(keyname, "tkey", "any")
# test existent/non-existent keys in the keyring
adapted_keyring = dns.tsig.GSSTSigAdapter(keyring)
# create a response, TKEY and turn it into bytes, simulating the server
# sending the response to the query
tkey_response = dns.message.make_response(tkey_message)
- key = base64.b64decode('KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY')
- tkey = dns.rdtypes.ANY.TKEY.TKEY(dns.rdataclass.ANY,
- dns.rdatatype.TKEY,
- dns.name.from_text('gss-tsig.'),
- 1594203795, 1594206664,
- 3, 0, key)
+ key = base64.b64decode("KEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEYKEY")
+ tkey = dns.rdtypes.ANY.TKEY.TKEY(
+ dns.rdataclass.ANY,
+ dns.rdatatype.TKEY,
+ dns.name.from_text("gss-tsig."),
+ 1594203795,
+ 1594206664,
+ 3,
+ 0,
+ key,
+ )
# add the TKEY answer and sign it
tkey_response.set_rcode(dns.rcode.NOERROR)
tkey_response.answer = [
- dns.rrset.from_rdata(dns.name.from_text(keyname), 0, tkey)]
- tkey_response.use_tsig(keyring=dns.tsig.GSSTSigAdapter(keyring),
- keyname=gsskeyname,
- algorithm=dns.tsig.GSS_TSIG)
+ dns.rrset.from_rdata(dns.name.from_text(keyname), 0, tkey)
+ ]
+ tkey_response.use_tsig(
+ keyring=dns.tsig.GSSTSigAdapter(keyring),
+ keyname=gsskeyname,
+ algorithm=dns.tsig.GSS_TSIG,
+ )
# "send" it to the client
tkey_wire = tkey_response.to_wire()
# create example message and go to/from wire to simulate sign/verify
# of regular messages
- a_message = dns.message.make_query('example', 'a')
+ a_message = dns.message.make_query("example", "a")
a_message.use_tsig(dns.tsig.GSSTSigAdapter(keyring), gsskeyname)
a_wire = a_message.to_wire()
# not raising is passing
self.assertEqual(gssapi_context_mock.verify_signature.call_count, 3)
def test_sign_and_validate(self):
- m = dns.message.make_query('example', 'a')
+ m = dns.message.make_query("example", "a")
m.use_tsig(keyring, keyname)
w = m.to_wire()
# not raising is passing
dns.message.from_wire(w, keyring)
def test_validate_with_bad_keyring(self):
- m = dns.message.make_query('example', 'a')
+ m = dns.message.make_query("example", "a")
m.use_tsig(keyring, keyname)
w = m.to_wire()
dns.message.from_wire(w, lambda m, n: None)
def test_sign_and_validate_with_other_data(self):
- m = dns.message.make_query('example', 'a')
- m.use_tsig(keyring, keyname, other_data=b'other')
+ m = dns.message.make_query("example", "a")
+ m.use_tsig(keyring, keyname, other_data=b"other")
w = m.to_wire()
# not raising is passing
dns.message.from_wire(w, keyring)
def test_sign_respond_and_validate(self):
- mq = dns.message.make_query('example', 'a')
+ mq = dns.message.make_query("example", "a")
mq.use_tsig(keyring, keyname)
wq = mq.to_wire()
mq_with_tsig = dns.message.from_wire(wq, keyring)
wr = mr.to_wire()
dns.message.from_wire(wr, keyring, request_mac=mq_with_tsig.mac)
- def make_message_pair(self, qname='example', rdtype='A', tsig_error=0):
+ def make_message_pair(self, qname="example", rdtype="A", tsig_error=0):
q = dns.message.make_query(qname, rdtype)
q.use_tsig(keyring=keyring, keyname=keyname)
q.to_wire() # to set q.mac
r = dns.message.make_response(q, tsig_error=tsig_error)
- return(q, r)
+ return (q, r)
def test_peer_errors(self):
- items = [(dns.rcode.BADSIG, dns.tsig.PeerBadSignature),
- (dns.rcode.BADKEY, dns.tsig.PeerBadKey),
- (dns.rcode.BADTIME, dns.tsig.PeerBadTime),
- (dns.rcode.BADTRUNC, dns.tsig.PeerBadTruncation),
- (99, dns.tsig.PeerError),
- ]
+ items = [
+ (dns.rcode.BADSIG, dns.tsig.PeerBadSignature),
+ (dns.rcode.BADKEY, dns.tsig.PeerBadKey),
+ (dns.rcode.BADTIME, dns.tsig.PeerBadTime),
+ (dns.rcode.BADTRUNC, dns.tsig.PeerBadTruncation),
+ (99, dns.tsig.PeerError),
+ ]
for err, ex in items:
q, r = self.make_message_pair(tsig_error=err)
w = r.to_wire()
+
def bad():
dns.message.from_wire(w, keyring=keyring, request_mac=q.mac)
+
self.assertRaises(ex, bad)
def _test_truncated_algorithm(self, alg, length):
- key = dns.tsig.Key('foo', b'abcdefg', algorithm=alg)
- q = dns.message.make_query('example', 'a')
+ key = dns.tsig.Key("foo", b"abcdefg", algorithm=alg)
+ q = dns.message.make_query("example", "a")
q.use_tsig(key)
q2 = dns.message.from_wire(q.to_wire(), keyring=key)
self._test_truncated_algorithm(dns.tsig.HMAC_SHA512_256, 256)
def _test_text_format(self, alg):
- key = dns.tsig.Key('foo', b'abcdefg', algorithm=alg)
- q = dns.message.make_query('example', 'a')
+ key = dns.tsig.Key("foo", b"abcdefg", algorithm=alg)
+ q = dns.message.make_query("example", "a")
q.use_tsig(key)
_ = q.to_wire()
text = q.tsig[0].to_text()
- tsig2 = dns.rdata.from_text('ANY', 'TSIG', text)
+ tsig2 = dns.rdata.from_text("ANY", "TSIG", text)
self.assertEqual(tsig2, q.tsig[0])
- q = dns.message.make_query('example', 'a')
- q.use_tsig(key, other_data=b'abc')
+ q = dns.message.make_query("example", "a")
+ q.use_tsig(key, other_data=b"abc")
q.use_tsig(key)
_ = q.to_wire()
text = q.tsig[0].to_text()
- tsig2 = dns.rdata.from_text('ANY', 'TSIG', text)
+ tsig2 = dns.rdata.from_text("ANY", "TSIG", text)
self.assertEqual(tsig2, q.tsig[0])
def test_text_hmac_sha256_128(self):
self._test_text_format(dns.tsig.HMAC_SHA512_256)
def test_non_gss_key_repr(self):
- key = dns.tsig.Key('foo', b'0123456789abcdef' * 2,
- algorithm=dns.tsig.HMAC_SHA256)
- self.assertEqual(repr(key),
- "<DNS key name='foo.', algorithm='hmac-sha256.', " +
- "secret=" +
- "'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY='>")
+ key = dns.tsig.Key(
+ "foo", b"0123456789abcdef" * 2, algorithm=dns.tsig.HMAC_SHA256
+ )
+ self.assertEqual(
+ repr(key),
+ "<DNS key name='foo.', algorithm='hmac-sha256.', "
+ + "secret="
+ + "'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY='>",
+ )
def test_gss_key_repr(self):
- key = dns.tsig.Key('foo', None,
- algorithm=dns.tsig.GSS_TSIG)
- self.assertEqual(repr(key),
- "<DNS key name='foo.', algorithm='gss-tsig.'>")
+ key = dns.tsig.Key("foo", None, algorithm=dns.tsig.GSS_TSIG)
+ self.assertEqual(repr(key), "<DNS key name='foo.', algorithm='gss-tsig.'>")
import dns.tsig
import dns.tsigkeyring
-text_keyring = {
- 'keyname.' : ('hmac-sha256.', 'NjHwPsMKjdN++dOfE5iAiQ==')
-}
+text_keyring = {"keyname.": ("hmac-sha256.", "NjHwPsMKjdN++dOfE5iAiQ==")}
-alt_text_keyring = {
- 'keyname.' : (dns.tsig.HMAC_SHA256, 'NjHwPsMKjdN++dOfE5iAiQ==')
-}
+alt_text_keyring = {"keyname.": (dns.tsig.HMAC_SHA256, "NjHwPsMKjdN++dOfE5iAiQ==")}
-old_text_keyring = {
- 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
-}
+old_text_keyring = {"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="}
-key = dns.tsig.Key('keyname.', 'NjHwPsMKjdN++dOfE5iAiQ==')
+key = dns.tsig.Key("keyname.", "NjHwPsMKjdN++dOfE5iAiQ==")
-rich_keyring = { key.name : key }
+rich_keyring = {key.name: key}
-old_rich_keyring = { key.name : key.secret }
+old_rich_keyring = {key.name: key.secret}
-class TSIGKeyRingTestCase(unittest.TestCase):
+class TSIGKeyRingTestCase(unittest.TestCase):
def test_from_text(self):
"""text keyring -> rich keyring"""
rkeyring = dns.tsigkeyring.from_text(text_keyring)
import dns.ttl
-class TTLTestCase(unittest.TestCase):
+class TTLTestCase(unittest.TestCase):
def test_bind_style_ok(self):
- ttl = dns.ttl.from_text('2w1d1h1m1s')
+ ttl = dns.ttl.from_text("2w1d1h1m1s")
self.assertEqual(ttl, 2 * 604800 + 86400 + 3600 + 60 + 1)
def test_bind_style_ok2(self):
# no one should do this, but it is legal! :)
- ttl = dns.ttl.from_text('1s2w1m1d1h')
+ ttl = dns.ttl.from_text("1s2w1m1d1h")
self.assertEqual(ttl, 2 * 604800 + 86400 + 3600 + 60 + 1)
def test_bind_style_bad_unit(self):
with self.assertRaises(dns.ttl.BadTTL):
- dns.ttl.from_text('5y')
+ dns.ttl.from_text("5y")
def test_bind_style_no_unit(self):
with self.assertRaises(dns.ttl.BadTTL):
- dns.ttl.from_text('1d5')
+ dns.ttl.from_text("1d5")
def test_bind_style_leading_unit(self):
with self.assertRaises(dns.ttl.BadTTL):
- dns.ttl.from_text('s')
+ dns.ttl.from_text("s")
def test_bind_style_unit_without_digits(self):
with self.assertRaises(dns.ttl.BadTTL):
- dns.ttl.from_text('1mw')
+ dns.ttl.from_text("1mw")
def test_empty(self):
with self.assertRaises(dns.ttl.BadTTL):
- dns.ttl.from_text('')
+ dns.ttl.from_text("")
import dns.rdataset
import dns.tsigkeyring
+
def hextowire(hex):
- return binascii.unhexlify(hex.replace(' ', '').encode())
+ return binascii.unhexlify(hex.replace(" ", "").encode())
+
goodwire = hextowire(
- '0001 2800 0001 0005 0007 0000'
- '076578616d706c6500 0006 0001'
- '03666f6fc00c 00ff 00ff 00000000 0000'
- 'c019 0001 00ff 00000000 0000'
- '03626172c00c 0001 0001 00000000 0004 0a000005'
- '05626c617a32c00c 00ff 00fe 00000000 0000'
- 'c049 0001 00fe 00000000 0000'
- 'c019 0001 00ff 00000000 0000'
- 'c019 0001 0001 0000012c 0004 0a000001'
- 'c019 0001 0001 0000012c 0004 0a000002'
- 'c035 0001 0001 0000012c 0004 0a000003'
- 'c035 0001 00fe 00000000 0004 0a000004'
- '04626c617ac00c 0001 00ff 00000000 0000'
- 'c049 00ff 00ff 00000000 0000'
+ "0001 2800 0001 0005 0007 0000"
+ "076578616d706c6500 0006 0001"
+ "03666f6fc00c 00ff 00ff 00000000 0000"
+ "c019 0001 00ff 00000000 0000"
+ "03626172c00c 0001 0001 00000000 0004 0a000005"
+ "05626c617a32c00c 00ff 00fe 00000000 0000"
+ "c049 0001 00fe 00000000 0000"
+ "c019 0001 00ff 00000000 0000"
+ "c019 0001 0001 0000012c 0004 0a000001"
+ "c019 0001 0001 0000012c 0004 0a000002"
+ "c035 0001 0001 0000012c 0004 0a000003"
+ "c035 0001 00fe 00000000 0004 0a000004"
+ "04626c617ac00c 0001 00ff 00000000 0000"
+ "c049 00ff 00ff 00000000 0000"
)
goodwirenone = hextowire(
- '0001 2800 0001 0000 0001 0000'
- '076578616d706c6500 0006 0001'
- '03666f6fc00c 0001 00fe 00000000 0004 01020304'
+ "0001 2800 0001 0000 0001 0000"
+ "076578616d706c6500 0006 0001"
+ "03666f6fc00c 0001 00fe 00000000 0004 01020304"
)
badwirenone = hextowire(
- '0001 2800 0001 0003 0000 0000'
- '076578616d706c6500 0006 0001'
- '03666f6fc00c 00ff 00ff 00000000 0000'
- 'c019 0001 00ff 00000000 0000'
- 'c019 0001 00fe 00000000 0004 01020304'
+ "0001 2800 0001 0003 0000 0000"
+ "076578616d706c6500 0006 0001"
+ "03666f6fc00c 00ff 00ff 00000000 0000"
+ "c019 0001 00ff 00000000 0000"
+ "c019 0001 00fe 00000000 0004 01020304"
)
badwireany = hextowire(
- '0001 2800 0001 0002 0000 0000'
- '076578616d706c6500 0006 0001'
- '03666f6fc00c 00ff 00ff 00000000 0000'
- 'c019 0001 00ff 00000000 0004 01020304'
+ "0001 2800 0001 0002 0000 0000"
+ "076578616d706c6500 0006 0001"
+ "03666f6fc00c 00ff 00ff 00000000 0000"
+ "c019 0001 00ff 00000000 0004 01020304"
)
badwireanyany = hextowire(
- '0001 2800 0001 0001 0000 0000'
- '076578616d706c6500 0006 0001'
- '03666f6fc00c 00ff 00ff 00000000 0004 01020304'
+ "0001 2800 0001 0001 0000 0000"
+ "076578616d706c6500 0006 0001"
+ "03666f6fc00c 00ff 00ff 00000000 0004 01020304"
)
badwirezonetype = hextowire(
- '0001 2800 0001 0000 0000 0000'
- '076578616d706c6500 0001 0001'
+ "0001 2800 0001 0000 0000 0000" "076578616d706c6500 0001 0001"
)
badwirezoneclass = hextowire(
- '0001 2800 0001 0000 0000 0000'
- '076578616d706c6500 0006 00ff'
+ "0001 2800 0001 0000 0000 0000" "076578616d706c6500 0006 00ff"
)
badwirezonemulti = hextowire(
- '0001 2800 0002 0000 0000 0000'
- '076578616d706c6500 0006 0001'
- 'c019 0006 0001'
+ "0001 2800 0002 0000 0000 0000" "076578616d706c6500 0006 0001" "c019 0006 0001"
)
badwirenozone = hextowire(
- '0001 2800 0000 0000 0001 0000'
- '03666f6f076578616d706c6500 0001 0001 00000030 0004 01020304'
+ "0001 2800 0000 0000 0001 0000"
+ "03666f6f076578616d706c6500 0001 0001 00000030 0004 01020304"
)
update_text = """id 1
foo 0 NONE A 10.0.0.2
"""
-class UpdateTestCase(unittest.TestCase):
- def test_to_wire1(self): # type: () -> None
- update = dns.update.Update('example')
+class UpdateTestCase(unittest.TestCase):
+ def test_to_wire1(self): # type: () -> None
+ update = dns.update.Update("example")
update.id = 1
- update.present('foo')
- update.present('foo', 'a')
- update.present('bar', 'a', '10.0.0.5')
- update.absent('blaz2')
- update.absent('blaz2', 'a')
- update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2')
- update.add('bar', 300, 'a', '10.0.0.3')
- update.delete('bar', 'a', '10.0.0.4')
- update.delete('blaz', 'a')
- update.delete('blaz2')
+ update.present("foo")
+ update.present("foo", "a")
+ update.present("bar", "a", "10.0.0.5")
+ update.absent("blaz2")
+ update.absent("blaz2", "a")
+ update.replace("foo", 300, "a", "10.0.0.1", "10.0.0.2")
+ update.add("bar", 300, "a", "10.0.0.3")
+ update.delete("bar", "a", "10.0.0.4")
+ update.delete("blaz", "a")
+ update.delete("blaz2")
self.assertEqual(update.to_wire(), goodwire)
- def test_to_wire2(self): # type: () -> None
- update = dns.update.Update('example')
+ def test_to_wire2(self): # type: () -> None
+ update = dns.update.Update("example")
update.id = 1
- update.present('foo')
- update.present('foo', 'a')
- update.present('bar', 'a', '10.0.0.5')
- update.absent('blaz2')
- update.absent('blaz2', 'a')
- update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2')
- update.add('bar', 300, dns.rdata.from_text(1, 1, '10.0.0.3'))
- update.delete('bar', 'a', '10.0.0.4')
- update.delete('blaz', 'a')
- update.delete('blaz2')
+ update.present("foo")
+ update.present("foo", "a")
+ update.present("bar", "a", "10.0.0.5")
+ update.absent("blaz2")
+ update.absent("blaz2", "a")
+ update.replace("foo", 300, "a", "10.0.0.1", "10.0.0.2")
+ update.add("bar", 300, dns.rdata.from_text(1, 1, "10.0.0.3"))
+ update.delete("bar", "a", "10.0.0.4")
+ update.delete("blaz", "a")
+ update.delete("blaz2")
self.assertEqual(update.to_wire(), goodwire)
- def test_to_wire3(self): # type: () -> None
- update = dns.update.Update('example')
+ def test_to_wire3(self): # type: () -> None
+ update = dns.update.Update("example")
update.id = 1
- update.present('foo')
- update.present('foo', 'a')
- update.present('bar', 'a', '10.0.0.5')
- update.absent('blaz2')
- update.absent('blaz2', 'a')
- update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2')
- update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3'))
- update.delete('bar', 'a', '10.0.0.4')
- update.delete('blaz', 'a')
- update.delete('blaz2')
+ update.present("foo")
+ update.present("foo", "a")
+ update.present("bar", "a", "10.0.0.5")
+ update.absent("blaz2")
+ update.absent("blaz2", "a")
+ update.replace("foo", 300, "a", "10.0.0.1", "10.0.0.2")
+ update.add("bar", dns.rdataset.from_text(1, 1, 300, "10.0.0.3"))
+ update.delete("bar", "a", "10.0.0.4")
+ update.delete("blaz", "a")
+ update.delete("blaz2")
self.assertEqual(update.to_wire(), goodwire)
- def test_from_text1(self): # type: () -> None
+ def test_from_text1(self): # type: () -> None
update = dns.message.from_text(update_text)
self.assertTrue(isinstance(update, dns.update.UpdateMessage))
- w = update.to_wire(origin=dns.name.from_text('example'),
- want_shuffle=False)
+ w = update.to_wire(origin=dns.name.from_text("example"), want_shuffle=False)
self.assertEqual(w, goodwire)
def test_from_wire(self):
- origin = dns.name.from_text('example')
+ origin = dns.name.from_text("example")
u1 = dns.message.from_wire(goodwire, origin=origin)
u2 = dns.message.from_text(update_text, origin=origin)
self.assertEqual(u1, u2)
def test_good_explicit_delete_wire(self):
- name = dns.name.from_text('foo.example')
+ name = dns.name.from_text("foo.example")
u = dns.message.from_wire(goodwirenone)
self.assertEqual(u.update[0].name, name)
self.assertEqual(u.update[0].rdtype, dns.rdatatype.A)
self.assertEqual(u.update[0].rdclass, dns.rdataclass.IN)
self.assertTrue(u.update[0].deleting)
- self.assertEqual(u.update[0][0].address, '1.2.3.4')
+ self.assertEqual(u.update[0][0].address, "1.2.3.4")
def test_none_with_rdata_from_wire(self):
def bad():
dns.message.from_wire(badwirenone)
+
self.assertRaises(dns.exception.FormError, bad)
def test_any_with_rdata_from_wire(self):
def bad():
dns.message.from_wire(badwireany)
+
self.assertRaises(dns.exception.FormError, bad)
def test_any_any_with_rdata_from_wire(self):
def bad():
dns.message.from_wire(badwireanyany)
+
self.assertRaises(dns.exception.FormError, bad)
def test_bad_zone_type_from_wire(self):
def bad():
dns.message.from_wire(badwirezonetype)
+
self.assertRaises(dns.exception.FormError, bad)
def test_bad_zone_class_from_wire(self):
def bad():
dns.message.from_wire(badwirezoneclass)
+
self.assertRaises(dns.exception.FormError, bad)
def test_bad_zone_multi_from_wire(self):
def bad():
dns.message.from_wire(badwirezonemulti)
+
self.assertRaises(dns.exception.FormError, bad)
def test_no_zone_section_from_wire(self):
def bad():
dns.message.from_wire(badwirenozone)
+
self.assertRaises(dns.exception.FormError, bad)
def test_TSIG(self):
- keyring = dns.tsigkeyring.from_text({
- 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
- })
- update = dns.update.Update('example.', keyring=keyring)
- update.replace('host.example.', 300, 'A', '1.2.3.4')
+ keyring = dns.tsigkeyring.from_text({"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="})
+ update = dns.update.Update("example.", keyring=keyring)
+ update.replace("host.example.", 300, "A", "1.2.3.4")
wire = update.to_wire()
update2 = dns.message.from_wire(wire, keyring)
self.assertEqual(update, update2)
self.assertTrue(update.is_response(r))
def test_making_UpdateSection(self):
- self.assertEqual(dns.update.UpdateSection.make(0),
- dns.update.UpdateSection.make('ZONE'))
+ self.assertEqual(
+ dns.update.UpdateSection.make(0), dns.update.UpdateSection.make("ZONE")
+ )
with self.assertRaises(ValueError):
dns.update.UpdateSection.make(99)
def test_setters(self):
u = dns.update.UpdateMessage(id=1)
- qrrset = dns.rrset.RRset(dns.name.from_text('example'),
- dns.rdataclass.IN, dns.rdatatype.SOA)
- rrset = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1')
+ qrrset = dns.rrset.RRset(
+ dns.name.from_text("example"), dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ rrset = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1")
u.zone = [qrrset]
self.assertEqual(u.sections[0], [qrrset])
self.assertEqual(u.sections[1], [])
self.assertEqual(u.sections[3], [])
def test_added_rdataset(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
- u.add('foo', rds)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ u.add("foo", rds)
expected = dns.message.from_text(added_text)
self.assertEqual(u, expected)
def test_replaced_rdataset(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
- u.replace('foo', rds)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ u.replace("foo", rds)
expected = dns.message.from_text(replaced_text)
self.assertEqual(u, expected)
def test_delete_rdataset(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1', '10.0.0.2')
- u.delete('foo', rds)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1", "10.0.0.2")
+ u.delete("foo", rds)
expected = dns.message.from_text(deleted_text)
self.assertEqual(u, expected)
def test_added_rdata(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
- u.add('foo', 300, rd1)
- u.add('foo', 300, rd2)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
+ u.add("foo", 300, rd1)
+ u.add("foo", 300, rd2)
expected = dns.message.from_text(added_text)
self.assertEqual(u, expected)
def test_replaced_rdata(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
- u.replace('foo', 300, rd1)
- u.add('foo', 300, rd2)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
+ u.replace("foo", 300, rd1)
+ u.add("foo", 300, rd2)
expected = dns.message.from_text(replaced_text)
self.assertEqual(u, expected)
def test_deleted_rdata(self):
- u = dns.update.UpdateMessage('example.', id=1)
- rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')
- rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2')
- u.delete('foo', rd1)
- u.delete('foo', rd2)
+ u = dns.update.UpdateMessage("example.", id=1)
+ rd1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1")
+ rd2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2")
+ u.delete("foo", rd1)
+ u.delete("foo", rd2)
expected = dns.message.from_text(deleted_text)
self.assertEqual(u, expected)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()
class BinaryTestCase(unittest.TestCase):
-
def test_basic(self):
- wire = bytes.fromhex('0102010203040102')
+ wire = bytes.fromhex("0102010203040102")
p = dns.wire.Parser(wire)
self.assertEqual(p.get_uint16(), 0x0102)
with p.restrict_to(5):
def test_name(self):
# www.dnspython.org NS IN question
- wire = b'\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01'
- expected = dns.name.from_text('www.dnspython.org')
+ wire = b"\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01"
+ expected = dns.name.from_text("www.dnspython.org")
p = dns.wire.Parser(wire)
self.assertEqual(p.get_name(), expected)
self.assertEqual(p.get_uint16(), 2)
def test_relativized_name(self):
# www.dnspython.org NS IN question
- wire = b'\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01'
- origin = dns.name.from_text('dnspython.org')
- expected = dns.name.from_text('www', None)
+ wire = b"\x03www\x09dnspython\x03org\x00\x00\x02\x00\x01"
+ origin = dns.name.from_text("dnspython.org")
+ expected = dns.name.from_text("www", None)
p = dns.wire.Parser(wire)
self.assertEqual(p.get_name(origin), expected)
self.assertEqual(p.remaining(), 4)
def test_compressed_name(self):
# www.dnspython.org NS IN question
- wire = b'\x09dnspython\x03org\x00\x03www\xc0\x00'
- expected1 = dns.name.from_text('dnspython.org')
- expected2 = dns.name.from_text('www.dnspython.org')
+ wire = b"\x09dnspython\x03org\x00\x03www\xc0\x00"
+ expected1 = dns.name.from_text("dnspython.org")
+ expected2 = dns.name.from_text("www.dnspython.org")
p = dns.wire.Parser(wire)
self.assertEqual(p.get_name(), expected1)
self.assertEqual(p.get_name(), expected2)
self.assertEqual(p.current, len(wire))
def test_seek(self):
- wire = b'\x09dnspython\x03org\x00'
+ wire = b"\x09dnspython\x03org\x00"
p = dns.wire.Parser(wire)
p.seek(10)
self.assertEqual(p.get_uint8(), 3)
p.seek(len(wire) + 1)
def test_not_reading_everything_in_restriction(self):
- wire = bytes.fromhex('0102010203040102')
+ wire = bytes.fromhex("0102010203040102")
p = dns.wire.Parser(wire)
with self.assertRaises(dns.exception.FormError):
with p.restrict_to(5):
# don't read the other 4 bytes
def test_restriction_does_not_mask_exception(self):
- wire = bytes.fromhex('0102010203040102')
+ wire = bytes.fromhex("0102010203040102")
p = dns.wire.Parser(wire)
with self.assertRaises(NotImplementedError):
with p.restrict_to(5):
# those tests.
try:
from .nanonameserver import Server
+
_nanonameserver_available = True
except ImportError:
_nanonameserver_available = False
+
class Server(object):
pass
-axfr = '''id 1
+
+axfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns1 3600 IN A 10.0.0.1
ns2 3600 IN A 10.0.0.2
@ 3600 IN SOA foo bar 1 2 3 4 5
-'''
+"""
-axfr1 = '''id 1
+axfr1 = """id 1
opcode QUERY
rcode NOERROR
flags AA
@ 3600 IN SOA foo bar 1 2 3 4 5
@ 3600 IN NS ns1
@ 3600 IN NS ns2
-'''
-axfr2 = '''id 1
+"""
+axfr2 = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns1 3600 IN A 10.0.0.1
ns2 3600 IN A 10.0.0.2
@ 3600 IN SOA foo bar 1 2 3 4 5
-'''
+"""
base = """@ 3600 IN SOA foo bar 1 2 3 4 5
@ 3600 IN NS ns1
ns2 3600 IN A 10.0.0.2
"""
-axfr_unexpected_origin = '''id 1
+axfr_unexpected_origin = """id 1
opcode QUERY
rcode NOERROR
flags AA
;ANSWER
@ 3600 IN SOA foo bar 1 2 3 4 5
@ 3600 IN SOA foo bar 1 2 3 4 7
-'''
+"""
-ixfr = '''id 1
+ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
@ 3600 IN NS ns2
@ 3600 IN SOA foo bar 4 2 3 4 5
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
-compressed_ixfr = '''id 1
+compressed_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns2 3600 IN A 10.0.0.4
ns3 3600 IN A 10.0.0.3
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
ixfr_expected = """@ 3600 IN SOA foo bar 4 2 3 4 5
@ 3600 IN NS ns1
ns3 3600 IN A 10.0.0.3
"""
-ixfr_first_message = '''id 1
+ixfr_first_message = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
-ixfr_header = '''id 1
+ixfr_header = """id 1
opcode QUERY
rcode NOERROR
flags AA
;ANSWER
-'''
+"""
ixfr_body = [
- '@ 3600 IN SOA foo bar 1 2 3 4 5',
- 'bar.foo 300 IN MX 0 blaz.foo',
- 'ns2 3600 IN A 10.0.0.2',
- '@ 3600 IN SOA foo bar 2 2 3 4 5',
- 'ns2 3600 IN A 10.0.0.4',
- '@ 3600 IN SOA foo bar 2 2 3 4 5',
- '@ 3600 IN SOA foo bar 3 2 3 4 5',
- 'ns3 3600 IN A 10.0.0.3',
- '@ 3600 IN SOA foo bar 3 2 3 4 5',
- '@ 3600 IN NS ns2',
- '@ 3600 IN SOA foo bar 4 2 3 4 5',
- '@ 3600 IN SOA foo bar 4 2 3 4 5',
+ "@ 3600 IN SOA foo bar 1 2 3 4 5",
+ "bar.foo 300 IN MX 0 blaz.foo",
+ "ns2 3600 IN A 10.0.0.2",
+ "@ 3600 IN SOA foo bar 2 2 3 4 5",
+ "ns2 3600 IN A 10.0.0.4",
+ "@ 3600 IN SOA foo bar 2 2 3 4 5",
+ "@ 3600 IN SOA foo bar 3 2 3 4 5",
+ "ns3 3600 IN A 10.0.0.3",
+ "@ 3600 IN SOA foo bar 3 2 3 4 5",
+ "@ 3600 IN NS ns2",
+ "@ 3600 IN SOA foo bar 4 2 3 4 5",
+ "@ 3600 IN SOA foo bar 4 2 3 4 5",
]
ixfrs = [ixfr_first_message]
ixfrs.extend([ixfr_header + l for l in ixfr_body])
-good_empty_ixfr = '''id 1
+good_empty_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
@ 3600 IN SOA foo bar 1 2 3 4 5
-'''
+"""
-retry_tcp_ixfr = '''id 1
+retry_tcp_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
@ 3600 IN SOA foo bar 5 2 3 4 5
-'''
+"""
-bad_empty_ixfr = '''id 1
+bad_empty_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
;ANSWER
@ 3600 IN SOA foo bar 4 2 3 4 5
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
-unexpected_end_ixfr = '''id 1
+unexpected_end_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns2 3600 IN A 10.0.0.4
ns3 3600 IN A 10.0.0.3
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
-unexpected_end_ixfr_2 = '''id 1
+unexpected_end_ixfr_2 = """id 1
opcode QUERY
rcode NOERROR
flags AA
bar.foo 300 IN MX 0 blaz.foo
ns2 3600 IN A 10.0.0.2
@ 3600 IN NS ns2
-'''
+"""
-bad_serial_ixfr = '''id 1
+bad_serial_ixfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns2 3600 IN A 10.0.0.4
ns3 3600 IN A 10.0.0.3
@ 3600 IN SOA foo bar 4 2 3 4 5
-'''
+"""
-ixfr_axfr = '''id 1
+ixfr_axfr = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns1 3600 IN A 10.0.0.1
ns2 3600 IN A 10.0.0.2
@ 3600 IN SOA foo bar 1 2 3 4 5
-'''
+"""
+
def test_basic_axfr():
- z = dns.versioned.Zone('example.')
- m = dns.message.from_text(axfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.versioned.Zone("example.")
+ m = dns.message.from_text(axfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(base, 'example.')
+ ez = dns.zone.from_text(base, "example.")
assert z == ez
+
def test_basic_axfr_unversioned():
- z = dns.zone.Zone('example.')
- m = dns.message.from_text(axfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.Zone("example.")
+ m = dns.message.from_text(axfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(base, 'example.')
+ ez = dns.zone.from_text(base, "example.")
assert z == ez
+
def test_basic_axfr_two_parts():
- z = dns.versioned.Zone('example.')
- m1 = dns.message.from_text(axfr1, origin=z.origin,
- one_rr_per_rrset=True)
- m2 = dns.message.from_text(axfr2, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.versioned.Zone("example.")
+ m1 = dns.message.from_text(axfr1, origin=z.origin, one_rr_per_rrset=True)
+ m2 = dns.message.from_text(axfr2, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr:
done = xfr.process_message(m1)
assert not done
done = xfr.process_message(m2)
assert done
- ez = dns.zone.from_text(base, 'example.')
+ ez = dns.zone.from_text(base, "example.")
assert z == ez
+
def test_axfr_unexpected_origin():
- z = dns.versioned.Zone('example.')
- m = dns.message.from_text(axfr_unexpected_origin, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.versioned.Zone("example.")
+ m = dns.message.from_text(
+ axfr_unexpected_origin, origin=z.origin, one_rr_per_rrset=True
+ )
with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_basic_ixfr():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(ixfr_expected, 'example.')
+ ez = dns.zone.from_text(ixfr_expected, "example.")
assert z == ez
+
def test_basic_ixfr_unversioned():
- z = dns.zone.from_text(base, 'example.')
- m = dns.message.from_text(ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.")
+ m = dns.message.from_text(ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(ixfr_expected, 'example.')
+ ez = dns.zone.from_text(ixfr_expected, "example.")
assert z == ez
+
def test_compressed_ixfr():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(compressed_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(compressed_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(ixfr_expected, 'example.')
+ ez = dns.zone.from_text(ixfr_expected, "example.")
assert z == ez
+
def test_basic_ixfr_many_parts():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
done = False
for text in ixfrs:
assert not done
- m = dns.message.from_text(text, origin=z.origin,
- one_rr_per_rrset=True)
+ m = dns.message.from_text(text, origin=z.origin, one_rr_per_rrset=True)
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(ixfr_expected, 'example.')
+ ez = dns.zone.from_text(ixfr_expected, "example.")
assert z == ez
+
def test_good_empty_ixfr():
- z = dns.zone.from_text(ixfr_expected, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(good_empty_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(ixfr_expected, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(good_empty_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(ixfr_expected, 'example.')
+ ez = dns.zone.from_text(ixfr_expected, "example.")
assert z == ez
+
def test_retry_tcp_ixfr():
- z = dns.zone.from_text(ixfr_expected, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(retry_tcp_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(ixfr_expected, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(retry_tcp_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1, is_udp=True) as xfr:
with pytest.raises(dns.xfr.UseTCP):
xfr.process_message(m)
+
def test_bad_empty_ixfr():
- z = dns.zone.from_text(ixfr_expected, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(bad_empty_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(ixfr_expected, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(bad_empty_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=3) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_serial_went_backwards_ixfr():
- z = dns.zone.from_text(ixfr_expected, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(bad_empty_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(ixfr_expected, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(bad_empty_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=5) as xfr:
with pytest.raises(dns.xfr.SerialWentBackwards):
xfr.process_message(m)
+
def test_ixfr_is_axfr():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(ixfr_axfr, origin=z.origin,
- one_rr_per_rrset=True)
- with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=0xffffffff) as xfr:
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(ixfr_axfr, origin=z.origin, one_rr_per_rrset=True)
+ with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=0xFFFFFFFF) as xfr:
done = xfr.process_message(m)
assert done
- ez = dns.zone.from_text(base, 'example.')
+ ez = dns.zone.from_text(base, "example.")
assert z == ez
+
def test_ixfr_requires_serial():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
with pytest.raises(ValueError):
dns.xfr.Inbound(z, dns.rdatatype.IXFR)
+
def test_ixfr_unexpected_end_bad_diff_sequence():
# This is where we get the end serial, but haven't seen all of
# the expected diffs
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(unexpected_end_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(
+ unexpected_end_ixfr, origin=z.origin, one_rr_per_rrset=True
+ )
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_udp_ixfr_unexpected_end_just_stops():
# This is where everything looks good, but the IXFR just stops
# in the middle.
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(unexpected_end_ixfr_2, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(
+ unexpected_end_ixfr_2, origin=z.origin, one_rr_per_rrset=True
+ )
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1, is_udp=True) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_ixfr_bad_serial():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(bad_serial_ixfr, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(bad_serial_ixfr, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_no_udp_with_axfr():
- z = dns.versioned.Zone('example.')
+ z = dns.versioned.Zone("example.")
with pytest.raises(ValueError):
with dns.xfr.Inbound(z, dns.rdatatype.AXFR, is_udp=True) as xfr:
pass
-refused = '''id 1
+
+refused = """id 1
opcode QUERY
rcode REFUSED
flags AA
;QUESTION
example. IN AXFR
-'''
+"""
-bad_qname = '''id 1
+bad_qname = """id 1
opcode QUERY
rcode NOERROR
flags AA
;QUESTION
not-example. IN IXFR
-'''
+"""
-bad_qtype = '''id 1
+bad_qtype = """id 1
opcode QUERY
rcode NOERROR
flags AA
;QUESTION
example. IN AXFR
-'''
+"""
-soa_not_first = '''id 1
+soa_not_first = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
bar.foo 300 IN MX 0 blaz.foo
-'''
+"""
-soa_not_first_2 = '''id 1
+soa_not_first_2 = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ANSWER
@ 300 IN MX 0 blaz.foo
-'''
+"""
-no_answer = '''id 1
+no_answer = """id 1
opcode QUERY
rcode NOERROR
flags AA
example. IN IXFR
;ADDITIONAL
bar.foo 300 IN MX 0 blaz.foo
-'''
+"""
-axfr_answers_after_final_soa = '''id 1
+axfr_answers_after_final_soa = """id 1
opcode QUERY
rcode NOERROR
flags AA
ns2 3600 IN A 10.0.0.2
@ 3600 IN SOA foo bar 1 2 3 4 5
ns3 3600 IN A 10.0.0.3
-'''
+"""
+
def test_refused():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(refused, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(refused, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.xfr.TransferError):
xfr.process_message(m)
+
def test_bad_qname():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(bad_qname, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(bad_qname, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_bad_qtype():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(bad_qtype, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(bad_qtype, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_soa_not_first():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(soa_not_first, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(soa_not_first, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
- m = dns.message.from_text(soa_not_first_2, origin=z.origin,
- one_rr_per_rrset=True)
+ m = dns.message.from_text(soa_not_first_2, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_no_answer():
- z = dns.zone.from_text(base, 'example.',
- zone_factory=dns.versioned.Zone)
- m = dns.message.from_text(no_answer, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.zone.from_text(base, "example.", zone_factory=dns.versioned.Zone)
+ m = dns.message.from_text(no_answer, origin=z.origin, one_rr_per_rrset=True)
with dns.xfr.Inbound(z, dns.rdatatype.IXFR, serial=1) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
+
def test_axfr_answers_after_final_soa():
- z = dns.versioned.Zone('example.')
- m = dns.message.from_text(axfr_answers_after_final_soa, origin=z.origin,
- one_rr_per_rrset=True)
+ z = dns.versioned.Zone("example.")
+ m = dns.message.from_text(
+ axfr_answers_after_final_soa, origin=z.origin, one_rr_per_rrset=True
+ )
with dns.xfr.Inbound(z, dns.rdatatype.AXFR) as xfr:
with pytest.raises(dns.exception.FormError):
xfr.process_message(m)
-keyring = dns.tsigkeyring.from_text(
- {
- 'keyname.': 'NjHwPsMKjdN++dOfE5iAiQ=='
- }
-)
-keyname = dns.name.from_text('keyname')
+keyring = dns.tsigkeyring.from_text({"keyname.": "NjHwPsMKjdN++dOfE5iAiQ=="})
+
+keyname = dns.name.from_text("keyname")
+
def test_make_query_basic():
- z = dns.versioned.Zone('example.')
+ z = dns.versioned.Zone("example.")
(q, s) = dns.xfr.make_query(z)
assert q.question[0].rdtype == dns.rdatatype.AXFR
assert s is None
assert q.authority[0][0].serial == 10
assert s == 10
with z.writer() as txn:
- txn.add('@', 300, dns.rdata.from_text('in', 'soa', '. . 1 2 3 4 5'))
+ txn.add("@", 300, dns.rdata.from_text("in", "soa", ". . 1 2 3 4 5"))
(q, s) = dns.xfr.make_query(z)
assert q.question[0].rdtype == dns.rdatatype.IXFR
assert q.authority[0].rdtype == dns.rdatatype.SOA
def test_make_query_bad_serial():
- z = dns.versioned.Zone('example.')
+ z = dns.versioned.Zone("example.")
with pytest.raises(ValueError):
- dns.xfr.make_query(z, serial='hi')
+ dns.xfr.make_query(z, serial="hi")
with pytest.raises(ValueError):
dns.xfr.make_query(z, serial=-1)
with pytest.raises(ValueError):
dns.xfr.make_query(z, serial=4294967296)
+
def test_extract_serial_from_query():
- z = dns.versioned.Zone('example.')
+ z = dns.versioned.Zone("example.")
(q, s) = dns.xfr.make_query(z)
xs = dns.xfr.extract_serial_from_query(q)
assert s is None
xs = dns.xfr.extract_serial_from_query(q)
assert s == 10
assert s == xs
- q = dns.message.make_query('example', 'a')
+ q = dns.message.make_query("example", "a")
with pytest.raises(ValueError):
dns.xfr.extract_serial_from_query(q)
class XFRNanoNameserver(Server):
-
def __init__(self):
- super().__init__(origin=dns.name.from_text('example'))
+ super().__init__(origin=dns.name.from_text("example"))
def handle(self, request):
try:
text = ixfr
else:
text = axfr
- r = dns.message.from_text(text, one_rr_per_rrset=True,
- origin=self.origin)
+ r = dns.message.from_text(text, one_rr_per_rrset=True, origin=self.origin)
r.id = request.message.id
return r
except Exception:
pass
-@pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+
+@pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_sync_inbound_xfr():
with XFRNanoNameserver() as ns:
- zone = dns.versioned.Zone('example')
- dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- expected = dns.zone.from_text(ixfr_expected, 'example')
+ zone = dns.versioned.Zone("example")
+ dns.query.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ dns.query.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ expected = dns.zone.from_text(ixfr_expected, "example")
assert zone == expected
+
async def async_inbound_xfr():
with XFRNanoNameserver() as ns:
- zone = dns.versioned.Zone('example')
- await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone,
- port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone,
- port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- expected = dns.zone.from_text(ixfr_expected, 'example')
+ zone = dns.versioned.Zone("example")
+ await dns.asyncquery.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ await dns.asyncquery.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ expected = dns.zone.from_text(ixfr_expected, "example")
assert zone == expected
-@pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+
+@pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_asyncio_inbound_xfr():
- dns.asyncbackend.set_default_backend('asyncio')
+ dns.asyncbackend.set_default_backend("asyncio")
+
async def run():
await async_inbound_xfr()
+
asyncio.run(run())
+
#
# We don't need to do this as it's all generic code, but
# just for extra caution we do it for each backend.
try:
import trio
- @pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+ @pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_trio_inbound_xfr():
- dns.asyncbackend.set_default_backend('trio')
+ dns.asyncbackend.set_default_backend("trio")
+
async def run():
await async_inbound_xfr()
+
trio.run(run)
+
except ImportError:
pass
try:
import curio
- @pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+ @pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_curio_inbound_xfr():
- dns.asyncbackend.set_default_backend('curio')
+ dns.asyncbackend.set_default_backend("curio")
+
async def run():
await async_inbound_xfr()
+
curio.run(run)
+
except ImportError:
pass
class UDPXFRNanoNameserver(Server):
-
def __init__(self):
- super().__init__(origin=dns.name.from_text('example'))
+ super().__init__(origin=dns.name.from_text("example"))
self.did_truncation = False
def handle(self, request):
self.did_truncation = True
else:
text = axfr
- r = dns.message.from_text(text, one_rr_per_rrset=True,
- origin=self.origin)
+ r = dns.message.from_text(text, one_rr_per_rrset=True, origin=self.origin)
r.id = request.message.id
return r
except Exception:
pass
-@pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+
+@pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_sync_retry_tcp_inbound_xfr():
with UDPXFRNanoNameserver() as ns:
- zone = dns.versioned.Zone('example')
- dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- dns.query.inbound_xfr(ns.tcp_address[0], zone, port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- expected = dns.zone.from_text(ixfr_expected, 'example')
+ zone = dns.versioned.Zone("example")
+ dns.query.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ dns.query.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ expected = dns.zone.from_text(ixfr_expected, "example")
assert zone == expected
+
async def udp_async_inbound_xfr():
with UDPXFRNanoNameserver() as ns:
- zone = dns.versioned.Zone('example')
- await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone,
- port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- await dns.asyncquery.inbound_xfr(ns.tcp_address[0], zone,
- port=ns.tcp_address[1],
- udp_mode=dns.query.UDPMode.TRY_FIRST)
- expected = dns.zone.from_text(ixfr_expected, 'example')
+ zone = dns.versioned.Zone("example")
+ await dns.asyncquery.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ await dns.asyncquery.inbound_xfr(
+ ns.tcp_address[0],
+ zone,
+ port=ns.tcp_address[1],
+ udp_mode=dns.query.UDPMode.TRY_FIRST,
+ )
+ expected = dns.zone.from_text(ixfr_expected, "example")
assert zone == expected
-@pytest.mark.skipif(not _nanonameserver_available,
- reason="requires nanonameserver")
+
+@pytest.mark.skipif(not _nanonameserver_available, reason="requires nanonameserver")
def test_asyncio_retry_tcp_inbound_xfr():
- dns.asyncbackend.set_default_backend('asyncio')
+ dns.asyncbackend.set_default_backend("asyncio")
+
async def run():
await udp_async_inbound_xfr()
+
try:
runner = asyncio.run
except AttributeError:
+
def old_runner(awaitable):
loop = asyncio.get_event_loop()
return loop.run_until_complete(awaitable)
+
runner = old_runner
runner(run())
"""
include_text = """$INCLUDE "%s"
-""" % here("example")
+""" % here(
+ "example"
+)
bad_directive_text = """$FOO bar
$ORIGIN example.
_keep_output = True
+
def _rdata_sort(a):
return (a[0], a[2].rdclass, a[2].to_text())
+
def add_rdataset(msg, name, rds):
- rrset = msg.get_rrset(msg.answer, name, rds.rdclass, rds.rdtype,
- create=True, force_unique=True)
+ rrset = msg.get_rrset(
+ msg.answer, name, rds.rdclass, rds.rdtype, create=True, force_unique=True
+ )
for rd in rds:
rrset.add(rd, ttl=rds.ttl)
+
def make_xfr(zone):
- q = dns.message.make_query(zone.origin, 'AXFR')
+ q = dns.message.make_query(zone.origin, "AXFR")
msg = dns.message.make_response(q)
if zone.relativize:
msg.origin = zone.origin
soa_name = dns.name.empty
else:
soa_name = zone.origin
- soa = zone.find_rdataset(soa_name, 'SOA')
+ soa = zone.find_rdataset(soa_name, "SOA")
add_rdataset(msg, soa_name, soa)
for (name, rds) in zone.iterate_rdatasets():
if rds.rdtype == dns.rdatatype.SOA:
add_rdataset(msg, soa_name, soa)
return [msg]
+
def compare_files(test_name, a_name, b_name):
- with open(a_name, 'r') as a:
- with open(b_name, 'r') as b:
- differences = list(difflib.unified_diff(a.readlines(),
- b.readlines()))
+ with open(a_name, "r") as a:
+ with open(b_name, "r") as b:
+ differences = list(difflib.unified_diff(a.readlines(), b.readlines()))
if len(differences) == 0:
return True
else:
- print(f'{test_name} differences:')
+ print(f"{test_name} differences:")
sys.stdout.writelines(differences)
return False
-class ZoneTestCase(unittest.TestCase):
+class ZoneTestCase(unittest.TestCase):
def testFromFile1(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
ok = False
try:
- z.to_file(here('example1.out'), nl=b'\x0a')
- ok = compare_files('testFromFile1',
- here('example1.out'),
- here('example1.good'))
+ z.to_file(here("example1.out"), nl=b"\x0a")
+ ok = compare_files(
+ "testFromFile1", here("example1.out"), here("example1.good")
+ )
finally:
if not _keep_output:
- os.unlink(here('example1.out'))
+ os.unlink(here("example1.out"))
self.assertTrue(ok)
def testFromFile2(self):
- z = dns.zone.from_file(here('example'), 'example', relativize=False)
+ z = dns.zone.from_file(here("example"), "example", relativize=False)
ok = False
try:
- z.to_file(here('example2.out'), relativize=False, nl=b'\x0a')
- ok = compare_files('testFromFile2',
- here('example2.out'),
- here('example2.good'))
+ z.to_file(here("example2.out"), relativize=False, nl=b"\x0a")
+ ok = compare_files(
+ "testFromFile2", here("example2.out"), here("example2.good")
+ )
finally:
if not _keep_output:
- os.unlink(here('example2.out'))
+ os.unlink(here("example2.out"))
self.assertTrue(ok)
def testToFileTextualStream(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
f = StringIO()
z.to_file(f)
out = f.getvalue()
self.assertEqual(out, example_text_output)
def testToFileBinaryStream(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
f = BytesIO()
- z.to_file(f, nl=b'\n')
+ z.to_file(f, nl=b"\n")
out = f.getvalue()
f.close()
self.assertEqual(out, example_text_output.encode())
def testToFileTextual(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
try:
- f = open(here('example3-textual.out'), 'w')
+ f = open(here("example3-textual.out"), "w")
z.to_file(f)
f.close()
- ok = compare_files('testToFileTextual',
- here('example3-textual.out'),
- here('example3.good'))
+ ok = compare_files(
+ "testToFileTextual", here("example3-textual.out"), here("example3.good")
+ )
finally:
if not _keep_output:
- os.unlink(here('example3-textual.out'))
+ os.unlink(here("example3-textual.out"))
self.assertTrue(ok)
def testToFileBinary(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
try:
- f = open(here('example3-binary.out'), 'wb')
+ f = open(here("example3-binary.out"), "wb")
z.to_file(f)
f.close()
- ok = compare_files('testToFileBinary',
- here('example3-binary.out'),
- here('example3.good'))
+ ok = compare_files(
+ "testToFileBinary", here("example3-binary.out"), here("example3.good")
+ )
finally:
if not _keep_output:
- os.unlink(here('example3-binary.out'))
+ os.unlink(here("example3-binary.out"))
self.assertTrue(ok)
def testToFileFilename(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
try:
- z.to_file(here('example3-filename.out'))
- ok = compare_files('testToFileFilename',
- here('example3-filename.out'),
- here('example3.good'))
+ z.to_file(here("example3-filename.out"))
+ ok = compare_files(
+ "testToFileFilename",
+ here("example3-filename.out"),
+ here("example3.good"),
+ )
finally:
if not _keep_output:
- os.unlink(here('example3-filename.out'))
+ os.unlink(here("example3-filename.out"))
self.assertTrue(ok)
def testToText(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
ok = False
try:
- text_zone = z.to_text(nl='\x0a')
- f = open(here('example3.out'), 'w')
+ text_zone = z.to_text(nl="\x0a")
+ f = open(here("example3.out"), "w")
f.write(text_zone)
f.close()
- ok = compare_files('testToText',
- here('example3.out'),
- here('example3.good'))
+ ok = compare_files(
+ "testToText", here("example3.out"), here("example3.good")
+ )
finally:
if not _keep_output:
- os.unlink(here('example3.out'))
+ os.unlink(here("example3.out"))
self.assertTrue(ok)
def testToFileTextualWithOrigin(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
try:
- f = open(here('example4-textual.out'), 'w')
+ f = open(here("example4-textual.out"), "w")
z.to_file(f, want_origin=True)
f.close()
- ok = compare_files('testToFileTextualWithOrigin',
- here('example4-textual.out'),
- here('example4.good'))
+ ok = compare_files(
+ "testToFileTextualWithOrigin",
+ here("example4-textual.out"),
+ here("example4.good"),
+ )
finally:
if not _keep_output:
- os.unlink(here('example4-textual.out'))
+ os.unlink(here("example4-textual.out"))
self.assertTrue(ok)
def testToFileBinaryWithOrigin(self):
- z = dns.zone.from_file(here('example'), 'example')
+ z = dns.zone.from_file(here("example"), "example")
try:
- f = open(here('example4-binary.out'), 'wb')
+ f = open(here("example4-binary.out"), "wb")
z.to_file(f, want_origin=True)
f.close()
- ok = compare_files('testToFileBinaryWithOrigin',
- here('example4-binary.out'),
- here('example4.good'))
+ ok = compare_files(
+ "testToFileBinaryWithOrigin",
+ here("example4-binary.out"),
+ here("example4.good"),
+ )
finally:
if not _keep_output:
- os.unlink(here('example4-binary.out'))
+ os.unlink(here("example4-binary.out"))
self.assertTrue(ok)
def testFromText(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
f = StringIO()
names = list(z.nodes.keys())
names.sort()
for n in names:
f.write(z[n].to_text(n))
- f.write('\n')
+ f.write("\n")
self.assertEqual(f.getvalue(), example_text_output)
def testTorture1(self):
# and then back out, and see if we get equal rdatas.
#
f = BytesIO()
- o = dns.name.from_text('example.')
- z = dns.zone.from_file(here('example'), o)
+ o = dns.name.from_text("example.")
+ z = dns.zone.from_file(here("example"), o)
for node in z.values():
for rds in node:
for rd in rds:
f.truncate()
rd.to_wire(f, origin=o)
wire = f.getvalue()
- rd2 = dns.rdata.from_wire(rds.rdclass, rds.rdtype,
- wire, 0, len(wire),
- origin=o)
+ rd2 = dns.rdata.from_wire(
+ rds.rdclass, rds.rdtype, wire, 0, len(wire), origin=o
+ )
self.assertEqual(rd, rd2)
def testEqual(self):
- z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
- z2 = dns.zone.from_text(example_text_output, 'example.',
- relativize=True)
+ z1 = dns.zone.from_text(example_text, "example.", relativize=True)
+ z2 = dns.zone.from_text(example_text_output, "example.", relativize=True)
self.assertEqual(z1, z2)
def testNotEqual1(self):
- z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
- z2 = dns.zone.from_text(something_quite_similar, 'example.',
- relativize=True)
+ z1 = dns.zone.from_text(example_text, "example.", relativize=True)
+ z2 = dns.zone.from_text(something_quite_similar, "example.", relativize=True)
self.assertNotEqual(z1, z2)
def testNotEqual2(self):
- z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
- z2 = dns.zone.from_text(something_different, 'example.',
- relativize=True)
+ z1 = dns.zone.from_text(example_text, "example.", relativize=True)
+ z2 = dns.zone.from_text(something_different, "example.", relativize=True)
self.assertNotEqual(z1, z2)
def testNotEqual3(self):
- z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
- z2 = dns.zone.from_text(something_different, 'example2.',
- relativize=True)
+ z1 = dns.zone.from_text(example_text, "example.", relativize=True)
+ z2 = dns.zone.from_text(something_different, "example2.", relativize=True)
self.assertNotEqual(z1, z2)
def testFindRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rds = z.find_rdataset('@', 'soa')
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rds = z.find_rdataset("@", "soa")
+ exrds = dns.rdataset.from_text("IN", "SOA", 300, "foo bar 1 2 3 4 5")
self.assertEqual(rds, exrds)
def testFindRdataset2(self):
def bad():
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- z.find_rdataset('@', 'loc')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ z.find_rdataset("@", "loc")
+
self.assertRaises(KeyError, bad)
def testFindRRset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rrs = z.find_rrset('@', 'soa')
- exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rrs = z.find_rrset("@", "soa")
+ exrrs = dns.rrset.from_text("@", 300, "IN", "SOA", "foo bar 1 2 3 4 5")
self.assertEqual(rrs, exrrs)
def testFindRRset2(self):
def bad():
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- z.find_rrset('@', 'loc')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ z.find_rrset("@", "loc")
+
self.assertRaises(KeyError, bad)
def testGetRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rds = z.get_rdataset('@', 'soa')
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rds = z.get_rdataset("@", "soa")
+ exrds = dns.rdataset.from_text("IN", "SOA", 300, "foo bar 1 2 3 4 5")
self.assertEqual(rds, exrds)
def testGetRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rds = z.get_rdataset('@', 'loc')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rds = z.get_rdataset("@", "loc")
self.assertTrue(rds is None)
def testGetRdatasetWithRelativeNameFromAbsoluteZone(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=False)
- rds = z.get_rdataset(dns.name.empty, 'soa')
+ z = dns.zone.from_text(example_text, "example.", relativize=False)
+ rds = z.get_rdataset(dns.name.empty, "soa")
self.assertIsNotNone(rds)
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo.example. bar.example. 1 2 3 4 5')
+ exrds = dns.rdataset.from_text(
+ "IN", "SOA", 300, "foo.example. bar.example. 1 2 3 4 5"
+ )
self.assertEqual(rds, exrds)
def testGetRRset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rrs = z.get_rrset('@', 'soa')
- exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rrs = z.get_rrset("@", "soa")
+ exrrs = dns.rrset.from_text("@", 300, "IN", "SOA", "foo bar 1 2 3 4 5")
self.assertEqual(rrs, exrrs)
def testGetRRset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rrs = z.get_rrset('@', 'loc')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rrs = z.get_rrset("@", "loc")
self.assertTrue(rrs is None)
def testReplaceRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rdataset = dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4')
- z.replace_rdataset('@', rdataset)
- rds = z.get_rdataset('@', 'ns')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rdataset = dns.rdataset.from_text("in", "ns", 300, "ns3", "ns4")
+ z.replace_rdataset("@", rdataset)
+ rds = z.get_rdataset("@", "ns")
self.assertTrue(rds is rdataset)
def testReplaceRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rdataset = dns.rdataset.from_text('in', 'txt', 300, '"foo"')
- z.replace_rdataset('@', rdataset)
- rds = z.get_rdataset('@', 'txt')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rdataset = dns.rdataset.from_text("in", "txt", 300, '"foo"')
+ z.replace_rdataset("@", rdataset)
+ rds = z.get_rdataset("@", "txt")
self.assertTrue(rds is rdataset)
def testDeleteRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- z.delete_rdataset('@', 'ns')
- rds = z.get_rdataset('@', 'ns')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ z.delete_rdataset("@", "ns")
+ rds = z.get_rdataset("@", "ns")
self.assertTrue(rds is None)
def testDeleteRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- z.delete_rdataset('ns1', 'a')
- node = z.get_node('ns1')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ z.delete_rdataset("ns1", "a")
+ node = z.get_node("ns1")
self.assertTrue(node is None)
def testNodeFindRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
+ exrds = dns.rdataset.from_text("IN", "SOA", 300, "foo bar 1 2 3 4 5")
self.assertEqual(rds, exrds)
def testNodeFindRdataset2(self):
def bad():
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
+
self.assertRaises(KeyError, bad)
def testNodeFindRdataset3(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
- rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG,
- dns.rdatatype.A, create=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
+ rds = node.find_rdataset(
+ dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.A, create=True
+ )
self.assertEqual(rds.rdclass, dns.rdataclass.IN)
self.assertEqual(rds.rdtype, dns.rdatatype.RRSIG)
self.assertEqual(rds.covers, dns.rdatatype.A)
def testNodeGetRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
+ exrds = dns.rdataset.from_text("IN", "SOA", 300, "foo bar 1 2 3 4 5")
self.assertEqual(rds, exrds)
def testNodeGetRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
self.assertTrue(rds is None)
def testNodeDeleteRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
self.assertTrue(rds is None)
def testNodeDeleteRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- node = z['@']
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ node = z["@"]
node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
self.assertTrue(rds is None)
def testIterateNodes(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
count = 0
for n in z:
count += 1
self.assertEqual(count, 4)
def testIterateRdatasets(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- ns = [n for n, r in z.iterate_rdatasets('A')]
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ ns = [n for n, r in z.iterate_rdatasets("A")]
ns.sort()
- self.assertEqual(ns, [dns.name.from_text('ns1', None),
- dns.name.from_text('ns2', None)])
+ self.assertEqual(
+ ns, [dns.name.from_text("ns1", None), dns.name.from_text("ns2", None)]
+ )
def testIterateAllRdatasets(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
ns = [n for n, r in z.iterate_rdatasets()]
ns.sort()
- self.assertEqual(ns, [dns.name.from_text('@', None),
- dns.name.from_text('@', None),
- dns.name.from_text('bar.foo', None),
- dns.name.from_text('ns1', None),
- dns.name.from_text('ns2', None)])
+ self.assertEqual(
+ ns,
+ [
+ dns.name.from_text("@", None),
+ dns.name.from_text("@", None),
+ dns.name.from_text("bar.foo", None),
+ dns.name.from_text("ns1", None),
+ dns.name.from_text("ns2", None),
+ ],
+ )
def testIterateRdatas(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- l = list(z.iterate_rdatas('A'))
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ l = list(z.iterate_rdatas("A"))
l.sort()
- exl = [(dns.name.from_text('ns1', None),
+ exl = [
+ (
+ dns.name.from_text("ns1", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ ]
self.assertEqual(l, exl)
def testIterateAllRdatas(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
l = list(z.iterate_rdatas())
l.sort(key=_rdata_sort)
- exl = [(dns.name.from_text('@', None),
+ exl = [
+ (
+ dns.name.from_text("@", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns1')),
- (dns.name.from_text('@', None),
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"),
+ ),
+ (
+ dns.name.from_text("@", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
- 'ns2')),
- (dns.name.from_text('@', None),
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"),
+ ),
+ (
+ dns.name.from_text("@", None),
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),
+ dns.rdata.from_text(
+ dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5"
+ ),
+ ),
+ (
+ dns.name.from_text("bar.foo", None),
300,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
- '0 blaz.foo')),
- (dns.name.from_text('ns1', None),
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"),
+ ),
+ (
+ dns.name.from_text("ns1", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.1')),
- (dns.name.from_text('ns2', None),
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"),
+ ),
+ (
+ dns.name.from_text("ns2", None),
3600,
- dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
- '10.0.0.2'))]
+ dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"),
+ ),
+ ]
exl.sort(key=_rdata_sort)
self.assertEqual(l, exl)
def testNodeGetSetDel(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
n = z.node_factory()
- rds = dns.rdataset.from_text('IN', 'A', 300, '10.0.0.1')
+ rds = dns.rdataset.from_text("IN", "A", 300, "10.0.0.1")
n.replace_rdataset(rds)
- z['foo'] = n
- self.assertTrue(z.find_rdataset('foo', 'A') is rds)
- self.assertEqual(z['foo'], n)
- self.assertEqual(z.get('foo'), n)
- del z['foo']
- self.assertEqual(z.get('foo'), None)
+ z["foo"] = n
+ self.assertTrue(z.find_rdataset("foo", "A") is rds)
+ self.assertEqual(z["foo"], n)
+ self.assertEqual(z.get("foo"), n)
+ del z["foo"]
+ self.assertEqual(z.get("foo"), None)
with self.assertRaises(KeyError):
z[123] = n
with self.assertRaises(KeyError):
- z['foo.'] = n
+ z["foo."] = n
with self.assertRaises(KeyError):
- bn = z.find_node('bar')
- bn = z.find_node('bar', True)
+ bn = z.find_node("bar")
+ bn = z.find_node("bar", True)
self.assertTrue(isinstance(bn, dns.node.Node))
# The next two tests pass by not raising KeyError
- z.delete_node('foo')
- z.delete_node('bar')
+ z.delete_node("foo")
+ z.delete_node("bar")
def testBadReplacement(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- rds = dns.rdataset.from_text('CH', 'TXT', 300, 'hi')
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ rds = dns.rdataset.from_text("CH", "TXT", 300, "hi")
+
def bad():
- z.replace_rdataset('foo', rds)
+ z.replace_rdataset("foo", rds)
+
self.assertRaises(ValueError, bad)
def testTTLs(self):
- z = dns.zone.from_text(ttl_example_text, 'example.', relativize=True)
- n = z['@'] # type: dns.node.Node
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA))
+ z = dns.zone.from_text(ttl_example_text, "example.", relativize=True)
+ n = z["@"] # type: dns.node.Node
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
+ )
self.assertEqual(rds.ttl, 3600)
- n = z['ns1']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns1"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 86401)
- n = z['ns2']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns2"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 694861)
def testTTLFromSOA(self):
- z = dns.zone.from_text(ttl_from_soa_text, 'example.', relativize=True)
- n = z['@']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA))
+ z = dns.zone.from_text(ttl_from_soa_text, "example.", relativize=True)
+ n = z["@"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
+ )
self.assertEqual(rds.ttl, 3600)
soa_rd = rds[0]
- n = z['ns1']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns1"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 694861)
- n = z['ns2']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns2"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, soa_rd.minimum)
def testTTLFromLast(self):
- z = dns.zone.from_text(ttl_from_last_text, 'example.', check_origin=False)
- n = z['@']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NS))
+ z = dns.zone.from_text(ttl_from_last_text, "example.", check_origin=False)
+ n = z["@"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NS)
+ )
self.assertEqual(rds.ttl, 3600)
- n = z['ns1']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns1"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 3600)
- n = z['ns2']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ n = z["ns2"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 694861)
def testNoTTL(self):
def bad():
- dns.zone.from_text(no_ttl_text, 'example.', check_origin=False)
+ dns.zone.from_text(no_ttl_text, "example.", check_origin=False)
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testNoSOA(self):
def bad():
- dns.zone.from_text(no_soa_text, 'example.', relativize=True)
+ dns.zone.from_text(no_soa_text, "example.", relativize=True)
+
self.assertRaises(dns.zone.NoSOA, bad)
def testNoNS(self):
def bad():
- dns.zone.from_text(no_ns_text, 'example.', relativize=True)
+ dns.zone.from_text(no_ns_text, "example.", relativize=True)
+
self.assertRaises(dns.zone.NoNS, bad)
def testInclude(self):
- z1 = dns.zone.from_text(include_text, 'example.', relativize=True,
- allow_include=True)
- z2 = dns.zone.from_file(here('example'), 'example.', relativize=True)
+ z1 = dns.zone.from_text(
+ include_text, "example.", relativize=True, allow_include=True
+ )
+ z2 = dns.zone.from_file(here("example"), "example.", relativize=True)
self.assertEqual(z1, z2)
def testBadDirective(self):
def bad():
- dns.zone.from_text(bad_directive_text, 'example.', relativize=True)
+ dns.zone.from_text(bad_directive_text, "example.", relativize=True)
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testFirstRRStartsWithWhitespace(self):
# no name is specified, so default to the initial origin
- z = dns.zone.from_text(' 300 IN A 10.0.0.1', origin='example.',
- check_origin=False)
- n = z['@']
- rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
+ z = dns.zone.from_text(
+ " 300 IN A 10.0.0.1", origin="example.", check_origin=False
+ )
+ n = z["@"]
+ rds = cast(
+ dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
+ )
self.assertEqual(rds.ttl, 300)
def testZoneOrigin(self):
- z = dns.zone.Zone('example.')
- self.assertEqual(z.origin, dns.name.from_text('example.'))
+ z = dns.zone.Zone("example.")
+ self.assertEqual(z.origin, dns.name.from_text("example."))
+
def bad1():
- o = dns.name.from_text('example', None)
+ o = dns.name.from_text("example", None)
dns.zone.Zone(o)
+
self.assertRaises(ValueError, bad1)
+
def bad2():
dns.zone.Zone(cast(str, 1.0))
+
self.assertRaises(ValueError, bad2)
def testZoneOriginNone(self):
dns.zone.Zone(cast(str, None))
def testZoneFromXFR(self):
- z1_abs = dns.zone.from_text(example_text, 'example.', relativize=False)
+ z1_abs = dns.zone.from_text(example_text, "example.", relativize=False)
z2_abs = dns.zone.from_xfr(make_xfr(z1_abs), relativize=False)
self.assertEqual(z1_abs, z2_abs)
- z1_rel = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z1_rel = dns.zone.from_text(example_text, "example.", relativize=True)
z2_rel = dns.zone.from_xfr(make_xfr(z1_rel), relativize=True)
self.assertEqual(z1_rel, z2_rel)
def testCodec2003(self):
- z = dns.zone.from_text(codec_text, 'example.', relativize=True)
- n2003 = dns.name.from_text('xn--knigsgsschen-lcb0w', None)
- n2008 = dns.name.from_text('xn--knigsgchen-b4a3dun', None)
+ z = dns.zone.from_text(codec_text, "example.", relativize=True)
+ n2003 = dns.name.from_text("xn--knigsgsschen-lcb0w", None)
+ n2008 = dns.name.from_text("xn--knigsgchen-b4a3dun", None)
self.assertTrue(n2003 in z)
self.assertFalse(n2008 in z)
- rrs = z.find_rrset(n2003, 'NS')
+ rrs = z.find_rrset(n2003, "NS")
self.assertEqual(rrs[0].target, n2003)
- @unittest.skipUnless(dns.name.have_idna_2008,
- 'Python idna cannot be imported; no IDNA2008')
+ @unittest.skipUnless(
+ dns.name.have_idna_2008, "Python idna cannot be imported; no IDNA2008"
+ )
def testCodec2008(self):
- z = dns.zone.from_text(codec_text, 'example.', relativize=True,
- idna_codec=dns.name.IDNA_2008)
- n2003 = dns.name.from_text('xn--knigsgsschen-lcb0w', None)
- n2008 = dns.name.from_text('xn--knigsgchen-b4a3dun', None)
+ z = dns.zone.from_text(
+ codec_text, "example.", relativize=True, idna_codec=dns.name.IDNA_2008
+ )
+ n2003 = dns.name.from_text("xn--knigsgsschen-lcb0w", None)
+ n2008 = dns.name.from_text("xn--knigsgchen-b4a3dun", None)
self.assertFalse(n2003 in z)
self.assertTrue(n2008 in z)
- rrs = z.find_rrset(n2008, 'NS')
+ rrs = z.find_rrset(n2008, "NS")
self.assertEqual(rrs[0].target, n2008)
def testZoneMiscCases(self):
# test that leading whitespace followed by EOL is treated like
# a blank line, and that out-of-zone names are dropped.
- z1 = dns.zone.from_text(misc_cases_input, 'example.')
- z2 = dns.zone.from_text(misc_cases_expected, 'example.')
+ z1 = dns.zone.from_text(misc_cases_input, "example.")
+ z2 = dns.zone.from_text(misc_cases_expected, "example.")
self.assertEqual(z1, z2)
def testUnknownOrigin(self):
def bad():
- dns.zone.from_text('foo 300 in a 10.0.0.1')
+ dns.zone.from_text("foo 300 in a 10.0.0.1")
+
self.assertRaises(dns.zone.UnknownOrigin, bad)
def testBadClass(self):
def bad():
- dns.zone.from_text('foo 300 ch txt hi', 'example.')
+ dns.zone.from_text("foo 300 ch txt hi", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testUnknownRdatatype(self):
def bad():
- dns.zone.from_text('foo 300 BOGUSTYPE hi', 'example.')
+ dns.zone.from_text("foo 300 BOGUSTYPE hi", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad)
def testDangling(self):
def bad1():
- dns.zone.from_text('foo', 'example.')
+ dns.zone.from_text("foo", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad1)
+
def bad2():
- dns.zone.from_text('foo 300', 'example.')
+ dns.zone.from_text("foo 300", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad2)
+
def bad3():
- dns.zone.from_text('foo 300 in', 'example.')
+ dns.zone.from_text("foo 300 in", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad3)
+
def bad4():
- dns.zone.from_text('foo 300 in a', 'example.')
+ dns.zone.from_text("foo 300 in a", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad4)
+
def bad5():
- dns.zone.from_text('$TTL', 'example.')
+ dns.zone.from_text("$TTL", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad5)
+
def bad6():
- dns.zone.from_text('$ORIGIN', 'example.')
+ dns.zone.from_text("$ORIGIN", "example.")
+
self.assertRaises(dns.exception.SyntaxError, bad6)
def testUseLastTTL(self):
- z = dns.zone.from_text(last_ttl_input, 'example.')
- rds = z.find_rdataset('foo', 'A')
+ z = dns.zone.from_text(last_ttl_input, "example.")
+ rds = z.find_rdataset("foo", "A")
self.assertEqual(rds.ttl, 300)
def testDollarOriginSetsZoneOriginIfUnknown(self):
z = dns.zone.from_text(origin_sets_input)
- self.assertEqual(z.origin, dns.name.from_text('example'))
+ self.assertEqual(z.origin, dns.name.from_text("example"))
def testValidateNameRelativizesNameInZone(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
- self.assertEqual(z._validate_name('foo.bar.example.'),
- dns.name.from_text('foo.bar', None))
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
+ self.assertEqual(
+ z._validate_name("foo.bar.example."), dns.name.from_text("foo.bar", None)
+ )
def testComments(self):
- z = dns.zone.from_text(example_comments_text, 'example.',
- relativize=True)
+ z = dns.zone.from_text(example_comments_text, "example.", relativize=True)
f = StringIO()
z.to_file(f, want_comments=True)
out = f.getvalue()
self.assertEqual(out, example_comments_text_output)
def testUncomparable(self):
- z = dns.zone.from_text(example_comments_text, 'example.',
- relativize=True)
- self.assertFalse(z == 'a')
+ z = dns.zone.from_text(example_comments_text, "example.", relativize=True)
+ self.assertFalse(z == "a")
def testUnsorted(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True)
+ z = dns.zone.from_text(example_text, "example.", relativize=True)
f = StringIO()
z.to_file(f, sorted=False)
out = f.getvalue()
f.close()
- z2 = dns.zone.from_text(out, 'example.', relativize=True)
+ z2 = dns.zone.from_text(out, "example.", relativize=True)
self.assertEqual(z, z2)
def testNodeReplaceRdatasetConvertsRRsets(self):
node = dns.node.Node()
- rrs = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1')
+ rrs = dns.rrset.from_text("foo", 300, "in", "a", "10.0.0.1")
node.replace_rdataset(rrs)
rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
self.assertEqual(rds, rrs)
self.assertFalse(isinstance(rds, dns.rrset.RRset))
def testCnameAndOtherDataAddOther(self):
- z = dns.zone.from_text(example_cname, 'example.', relativize=True)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
- z.replace_rdataset('web', rds)
- z.replace_rdataset('web2', rds.copy())
- n = z.find_node('web')
+ z = dns.zone.from_text(example_cname, "example.", relativize=True)
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
+ z.replace_rdataset("web", rds)
+ z.replace_rdataset("web2", rds.copy())
+ n = z.find_node("web")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC))
- n = z.find_node('web2')
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC)
+ )
+ n = z.find_node("web2")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC3))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC3))
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC3))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC3)
+ )
def testCnameAndOtherDataAddCname(self):
- z = dns.zone.from_text(example_other_data, 'example.', relativize=True)
- rds = dns.rdataset.from_text('in', 'cname', 300, 'www')
- z.replace_rdataset('web', rds)
- n = z.find_node('web')
+ z = dns.zone.from_text(example_other_data, "example.", relativize=True)
+ rds = dns.rdataset.from_text("in", "cname", 300, "www")
+ z.replace_rdataset("web", rds)
+ n = z.find_node("web")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN,
- dns.rdatatype.CNAME),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC))
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.CNAME), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC)
+ )
def testCnameAndOtherDataInZonefile(self):
with self.assertRaises(dns.zonefile.CNAMEAndOtherData):
- dns.zone.from_text(example_cname_and_other_data, 'example.',
- relativize=True)
+ dns.zone.from_text(
+ example_cname_and_other_data, "example.", relativize=True
+ )
def testNameInZoneWithStr(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=False)
- self.assertTrue('ns1.example.' in z)
- self.assertTrue('bar.foo.example.' in z)
+ z = dns.zone.from_text(example_text, "example.", relativize=False)
+ self.assertTrue("ns1.example." in z)
+ self.assertTrue("bar.foo.example." in z)
def testNameInZoneWhereNameIsNotValid(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=False)
+ z = dns.zone.from_text(example_text, "example.", relativize=False)
with self.assertRaises(KeyError):
self.assertTrue(1 in z)
class VersionedZoneTestCase(unittest.TestCase):
def testUseTransaction(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
with self.assertRaises(dns.versioned.UseTransaction):
- z.find_node('not_there', True)
+ z.find_node("not_there", True)
with self.assertRaises(dns.versioned.UseTransaction):
- z.delete_node('not_there')
+ z.delete_node("not_there")
with self.assertRaises(dns.versioned.UseTransaction):
- z.find_rdataset('not_there', 'a', create=True)
+ z.find_rdataset("not_there", "a", create=True)
with self.assertRaises(dns.versioned.UseTransaction):
- z.get_rdataset('not_there', 'a', create=True)
+ z.get_rdataset("not_there", "a", create=True)
with self.assertRaises(dns.versioned.UseTransaction):
- z.delete_rdataset('not_there', 'a')
+ z.delete_rdataset("not_there", "a")
with self.assertRaises(dns.versioned.UseTransaction):
- z.replace_rdataset('not_there', None)
+ z.replace_rdataset("not_there", None)
def testImmutableNodes(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
- node = z.find_node('@')
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
+ node = z.find_node("@")
with self.assertRaises(TypeError):
- node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.RP,
- create=True)
+ node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.RP, create=True)
with self.assertRaises(TypeError):
- node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RP,
- create=True)
+ node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RP, create=True)
with self.assertRaises(TypeError):
node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
with self.assertRaises(TypeError):
node.replace_rdataset(None)
def testSelectDefaultPruningPolicy(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
z.set_pruning_policy(None)
self.assertEqual(z._pruning_policy, z._default_pruning_policy)
def testSetAlternatePruningPolicyInConstructor(self):
def never_prune(version):
return False
- z = dns.versioned.Zone('example', pruning_policy=never_prune)
+
+ z = dns.versioned.Zone("example", pruning_policy=never_prune)
self.assertEqual(z._pruning_policy, never_prune)
def testCannotSpecifyBothSerialAndVersionIdToReader(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
with self.assertRaises(ValueError):
z.reader(1, 1)
def testUnknownVersion(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
with self.assertRaises(KeyError):
z.reader(99999)
def testUnknownSerial(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
with self.assertRaises(KeyError):
z.reader(serial=99999)
def testNoRelativizeReader(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=False,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=False, zone_factory=dns.versioned.Zone
+ )
with z.reader(serial=1) as txn:
- rds = txn.get('example.', 'soa')
+ rds = txn.get("example.", "soa")
self.assertEqual(rds[0].serial, 1)
def testNoRelativizeReaderOriginInText(self):
- z = dns.zone.from_text(example_text, relativize=False,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, relativize=False, zone_factory=dns.versioned.Zone
+ )
with z.reader(serial=1) as txn:
- rds = txn.get('example.', 'soa')
+ rds = txn.get("example.", "soa")
self.assertEqual(rds[0].serial, 1)
def testNoRelativizeReaderAbsoluteGet(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=False,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=False, zone_factory=dns.versioned.Zone
+ )
with z.reader(serial=1) as txn:
- rds = txn.get(dns.name.empty, 'soa')
+ rds = txn.get(dns.name.empty, "soa")
self.assertEqual(rds[0].serial, 1)
def testCnameAndOtherDataAddOther(self):
- z = dns.zone.from_text(example_cname, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
- rds = dns.rdataset.from_text('in', 'a', 300, '10.0.0.1')
+ z = dns.zone.from_text(
+ example_cname, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
+ rds = dns.rdataset.from_text("in", "a", 300, "10.0.0.1")
with z.writer() as txn:
- txn.replace('web', rds)
- txn.replace('web2', rds.copy())
- n = z.find_node('web')
+ txn.replace("web", rds)
+ txn.replace("web2", rds.copy())
+ n = z.find_node("web")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC))
- n = z.find_node('web2')
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC)
+ )
+ n = z.find_node("web2")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC3))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC3))
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.A), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC3))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC3)
+ )
def testCnameAndOtherDataAddCname(self):
- z = dns.zone.from_text(example_other_data, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
- rds = dns.rdataset.from_text('in', 'cname', 300, 'www')
+ z = dns.zone.from_text(
+ example_other_data,
+ "example.",
+ relativize=True,
+ zone_factory=dns.versioned.Zone,
+ )
+ rds = dns.rdataset.from_text("in", "cname", 300, "www")
with z.writer() as txn:
- txn.replace('web', rds)
- n = z.find_node('web')
+ txn.replace("web", rds)
+ n = z.find_node("web")
self.assertEqual(len(n.rdatasets), 3)
- self.assertEqual(n.find_rdataset(dns.rdataclass.IN,
- dns.rdatatype.CNAME),
- rds)
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.NSEC))
- self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN,
- dns.rdatatype.RRSIG,
- dns.rdatatype.NSEC))
+ self.assertEqual(n.find_rdataset(dns.rdataclass.IN, dns.rdatatype.CNAME), rds)
+ self.assertIsNotNone(n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NSEC))
+ self.assertIsNotNone(
+ n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.RRSIG, dns.rdatatype.NSEC)
+ )
def testGetSoa(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
soa = z.get_soa()
self.assertTrue(soa.rdtype, dns.rdatatype.SOA)
self.assertEqual(soa.serial, 1)
def testGetSoaTxn(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
with z.reader(serial=1) as txn:
soa = z.get_soa(txn)
self.assertTrue(soa.rdtype, dns.rdatatype.SOA)
self.assertEqual(soa.serial, 1)
def testGetSoaEmptyZone(self):
- z = dns.zone.Zone('example.')
+ z = dns.zone.Zone("example.")
with self.assertRaises(dns.zone.NoSOA):
soa = z.get_soa()
def testGetRdataset1(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
- rds = z.get_rdataset('@', 'soa')
- exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
+ rds = z.get_rdataset("@", "soa")
+ exrds = dns.rdataset.from_text("IN", "SOA", 300, "foo bar 1 2 3 4 5")
self.assertEqual(rds, exrds)
def testGetRdataset2(self):
- z = dns.zone.from_text(example_text, 'example.', relativize=True,
- zone_factory=dns.versioned.Zone)
- rds = z.get_rdataset('@', 'loc')
+ z = dns.zone.from_text(
+ example_text, "example.", relativize=True, zone_factory=dns.versioned.Zone
+ )
+ rds = z.get_rdataset("@", "loc")
self.assertTrue(rds is None)
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
import dns.rrset
import dns.zone
+
class ZoneDigestTestCase(unittest.TestCase):
# Examples from RFC 8976, fixed per errata.
- simple_example = textwrap.dedent('''
+ simple_example = textwrap.dedent(
+ """
example. 86400 IN SOA ns1 admin 2018031900 (
1800 900 604800 86400 )
86400 IN NS ns1
777f98b8e730044c )
ns1 3600 IN A 203.0.113.63
ns2 3600 IN AAAA 2001:db8::63
- ''')
+ """
+ )
- complex_example = textwrap.dedent('''
+ complex_example = textwrap.dedent(
+ """
example. 86400 IN SOA ns1 admin 2018031900 (
1800 900 604800 86400 )
86400 IN NS ns1
6f77656420627574
2069676e6f726564
2e20616c6c6f7765 )
- ''')
+ """
+ )
- multiple_digests_example = textwrap.dedent('''
+ multiple_digests_example = textwrap.dedent(
+ """
example. 86400 IN SOA ns1 admin 2018031900 (
1800 900 604800 86400 )
example. 86400 IN NS ns1.example.
ns1.example. 3600 IN A 203.0.113.63
ns2.example. 86400 IN TXT "This example has multiple digests"
NS2.EXAMPLE. 3600 IN AAAA 2001:db8::63
- ''')
+ """
+ )
def _get_zonemd(self, zone):
- return zone.get_rdataset(zone.origin, 'ZONEMD')
+ return zone.get_rdataset(zone.origin, "ZONEMD")
def test_zonemd_simple(self):
- zone = dns.zone.from_text(self.simple_example, origin='example')
+ zone = dns.zone.from_text(self.simple_example, origin="example")
zone.verify_digest()
zonemd = self._get_zonemd(zone)
- self.assertEqual(zonemd[0],
- zone.compute_digest(zonemd[0].hash_algorithm))
+ self.assertEqual(zonemd[0], zone.compute_digest(zonemd[0].hash_algorithm))
def test_zonemd_simple_absolute(self):
- zone = dns.zone.from_text(self.simple_example, origin='example',
- relativize=False)
+ zone = dns.zone.from_text(
+ self.simple_example, origin="example", relativize=False
+ )
zone.verify_digest()
zonemd = self._get_zonemd(zone)
- self.assertEqual(zonemd[0],
- zone.compute_digest(zonemd[0].hash_algorithm))
+ self.assertEqual(zonemd[0], zone.compute_digest(zonemd[0].hash_algorithm))
def test_zonemd_complex(self):
- zone = dns.zone.from_text(self.complex_example, origin='example')
+ zone = dns.zone.from_text(self.complex_example, origin="example")
zone.verify_digest()
zonemd = self._get_zonemd(zone)
- self.assertEqual(zonemd[0],
- zone.compute_digest(zonemd[0].hash_algorithm))
+ self.assertEqual(zonemd[0], zone.compute_digest(zonemd[0].hash_algorithm))
def test_zonemd_multiple_digests(self):
- zone = dns.zone.from_text(self.multiple_digests_example,
- origin='example')
+ zone = dns.zone.from_text(self.multiple_digests_example, origin="example")
zone.verify_digest()
zonemd = self._get_zonemd(zone)
zone.verify_digest(rr)
def test_zonemd_no_digest(self):
- zone = dns.zone.from_text(self.simple_example, origin='example')
- zone.delete_rdataset(dns.name.empty, 'ZONEMD')
+ zone = dns.zone.from_text(self.simple_example, origin="example")
+ zone.delete_rdataset(dns.name.empty, "ZONEMD")
with self.assertRaises(dns.zone.NoDigest):
zone.verify_digest()
- sha384_hash = 'ab' * 48
- sha512_hash = 'ab' * 64
+ sha384_hash = "ab" * 48
+ sha512_hash = "ab" * 64
def test_zonemd_parse_rdata(self):
- dns.rdata.from_text('IN', 'ZONEMD', '100 1 1 ' + self.sha384_hash)
- dns.rdata.from_text('IN', 'ZONEMD', '100 1 2 ' + self.sha512_hash)
- dns.rdata.from_text('IN', 'ZONEMD', '100 100 1 ' + self.sha384_hash)
- dns.rdata.from_text('IN', 'ZONEMD', '100 1 100 abcd')
+ dns.rdata.from_text("IN", "ZONEMD", "100 1 1 " + self.sha384_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 1 2 " + self.sha512_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 100 1 " + self.sha384_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 1 100 abcd")
def test_zonemd_unknown_scheme(self):
- zone = dns.zone.from_text(self.simple_example, origin='example')
+ zone = dns.zone.from_text(self.simple_example, origin="example")
with self.assertRaises(dns.zone.UnsupportedDigestScheme):
zone.compute_digest(dns.zone.DigestHashAlgorithm.SHA384, 2)
def test_zonemd_unknown_hash_algorithm(self):
- zone = dns.zone.from_text(self.simple_example, origin='example')
+ zone = dns.zone.from_text(self.simple_example, origin="example")
with self.assertRaises(dns.zone.UnsupportedDigestHashAlgorithm):
zone.compute_digest(5)
def test_zonemd_invalid_digest_length(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('IN', 'ZONEMD', '100 1 2 ' + self.sha384_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 1 2 " + self.sha384_hash)
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('IN', 'ZONEMD', '100 2 1 ' + self.sha512_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 2 1 " + self.sha512_hash)
def test_zonemd_parse_rdata_reserved(self):
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('IN', 'ZONEMD', '100 0 1 ' + self.sha384_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 0 1 " + self.sha384_hash)
with self.assertRaises(dns.exception.SyntaxError):
- dns.rdata.from_text('IN', 'ZONEMD', '100 1 0 ' + self.sha384_hash)
+ dns.rdata.from_text("IN", "ZONEMD", "100 1 0 " + self.sha384_hash)
- sorting_zone = textwrap.dedent('''
+ sorting_zone = textwrap.dedent(
+ """
@ 86400 IN SOA ns1 admin 2018031900 (
1800 900 604800 86400 )
86400 IN NS ns1
86400 IN NS ns2
86400 IN RP n1.example. a.
86400 IN RP n1. b.
- ''')
-
+ """
+ )
+
def test_relative_zone_sorting(self):
- z1 = dns.zone.from_text(self.sorting_zone, 'example.', relativize=True)
- z2 = dns.zone.from_text(self.sorting_zone, 'example.', relativize=False)
+ z1 = dns.zone.from_text(self.sorting_zone, "example.", relativize=True)
+ z2 = dns.zone.from_text(self.sorting_zone, "example.", relativize=False)
zmd1 = z1.compute_digest(dns.zone.DigestHashAlgorithm.SHA384)
zmd2 = z2.compute_digest(dns.zone.DigestHashAlgorithm.SHA384)
self.assertEqual(zmd1, zmd2)
import dns.rdtypes.txtbase
+
class TTXT(dns.rdtypes.txtbase.TXTBase):
"""Test TXT-like record"""
import sys
import unittest
-if __name__ == '__main__':
- sys.path.insert(0, os.path.realpath('..'))
+if __name__ == "__main__":
+ sys.path.insert(0, os.path.realpath(".."))
if len(sys.argv) > 1:
pattern = sys.argv[1]
else:
- pattern = 'test*.py'
- suites = unittest.defaultTestLoader.discover('.', pattern)
+ pattern = "test*.py"
+ suites = unittest.defaultTestLoader.discover(".", pattern)
if not unittest.TextTestRunner(verbosity=2).run(suites).wasSuccessful():
sys.exit(1)
import inspect
import os.path
+
def here(filename):
return os.path.join(os.path.dirname(__file__), filename)
+
def enumerate_module(module, super_class):
"""Yield module attributes which are subclasses of given class"""
for attr_name in dir(module):
if inspect.isclass(attr) and issubclass(attr, super_class):
yield attr
+
def check_enum_exports(module, eq_callback, only=None):
"""Make sure module exports all mnemonics from enums"""
for attr in enumerate_module(module, enum.Enum):
if only is not None and attr not in only:
- #print('SKIP', attr)
+ # print('SKIP', attr)
continue
for flag, value in attr.__members__.items():
- #print(module, flag, value)
+ # print(module, flag, value)
eq_callback(getattr(module, flag), value)
# Generate a pickled mx RR for the current dnspython version
-mx = dns.rdata.from_text('in', 'mx', '10 mx.example.')
-filename = f'pickled-{dns.version.MAJOR}-{dns.version.MINOR}.pickle'
-with open(filename, 'wb') as f:
+mx = dns.rdata.from_text("in", "mx", "10 mx.example.")
+filename = f"pickled-{dns.version.MAJOR}-{dns.version.MINOR}.pickle"
+with open(filename, "wb") as f:
pickle.dump(mx, f)
-with open(filename, 'rb') as f:
+with open(filename, "rb") as f:
mx2 = pickle.load(f)
if mx == mx2:
- print('ok')
+ print("ok")
else:
- print('DIFFERENT!')
+ print("DIFFERENT!")
sys.exit(1)
-
import dns.rdatatype
-print('Rdatatypes')
-print('----------')
+print("Rdatatypes")
+print("----------")
print()
by_name = {}
for rdtype in dns.rdatatype.RdataType:
- short_name = str(rdtype).split('.')[1]
+ short_name = str(rdtype).split(".")[1]
by_name[short_name] = int(rdtype)
for k in sorted(by_name.keys()):
v = by_name[k]
- print(f'.. py:data:: dns.rdatatype.{k}')
- print(f' :annotation: = {v}')
+ print(f".. py:data:: dns.rdatatype.{k}")
+ print(f" :annotation: = {v}")