mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 13:11:15 -07:00
Bump dnspython from 2.2.1 to 2.3.0 (#1975)
* Bump dnspython from 2.2.1 to 2.3.0 Bumps [dnspython](https://github.com/rthalley/dnspython) from 2.2.1 to 2.3.0. - [Release notes](https://github.com/rthalley/dnspython/releases) - [Changelog](https://github.com/rthalley/dnspython/blob/master/doc/whatsnew.rst) - [Commits](https://github.com/rthalley/dnspython/compare/v2.2.1...v2.3.0) --- updated-dependencies: - dependency-name: dnspython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Update dnspython==2.3.0 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> [skip ci]
This commit is contained in:
parent
6910079330
commit
32c06a8b72
137 changed files with 7699 additions and 4277 deletions
372
lib/dns/rdata.py
372
lib/dns/rdata.py
|
@ -17,6 +17,8 @@
|
|||
|
||||
"""DNS rdata."""
|
||||
|
||||
from typing import Any, Dict, Optional, Tuple, Union
|
||||
|
||||
from importlib import import_module
|
||||
import base64
|
||||
import binascii
|
||||
|
@ -55,21 +57,22 @@ class NoRelativeRdataOrdering(dns.exception.DNSException):
|
|||
"""
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
|
@ -77,17 +80,19 @@ def _hexify(data, chunksize=_chunksize, separator=b' ', **kw):
|
|||
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."""
|
||||
|
||||
|
@ -96,14 +101,14 @@ def _escapify(qstring):
|
|||
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
|
||||
|
||||
|
||||
|
@ -114,9 +119,10 @@ def _truncate_bitmap(what):
|
|||
|
||||
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
|
||||
|
||||
|
@ -125,7 +131,7 @@ _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.
|
||||
|
@ -140,8 +146,9 @@ class Rdata:
|
|||
self.rdcomment = 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
|
||||
|
@ -160,12 +167,12 @@ class Rdata:
|
|||
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):
|
||||
def covers(self) -> dns.rdatatype.RdataType:
|
||||
"""Return the type a Rdata covers.
|
||||
|
||||
DNS SIG/RRSIG rdatas apply to a specific type; this type is
|
||||
|
@ -174,12 +181,12 @@ class Rdata:
|
|||
creating rdatasets, allowing the rdataset to contain only RRSIGs
|
||||
of a particular type, e.g. RRSIG(NS).
|
||||
|
||||
Returns an ``int``.
|
||||
Returns a ``dns.rdatatype.RdataType``.
|
||||
"""
|
||||
|
||||
return dns.rdatatype.NONE
|
||||
|
||||
def extended_rdatatype(self):
|
||||
def extended_rdatatype(self) -> int:
|
||||
"""Return a 32-bit type value, the least significant 16 bits of
|
||||
which are the ordinary DNS type, and the upper 16 bits of which are
|
||||
the "covered" type, if any.
|
||||
|
@ -189,7 +196,12 @@ class Rdata:
|
|||
|
||||
return self.covers() << 16 | self.rdtype
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
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``.
|
||||
|
@ -197,11 +209,22 @@ class Rdata:
|
|||
|
||||
raise NotImplementedError # pragma: no cover
|
||||
|
||||
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
|
||||
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=None, compress=None, origin=None,
|
||||
canonicalize=False):
|
||||
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``.
|
||||
|
@ -214,15 +237,18 @@ class Rdata:
|
|||
self._to_wire(f, compress, origin, canonicalize)
|
||||
return f.getvalue()
|
||||
|
||||
def to_generic(self, origin=None):
|
||||
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=None):
|
||||
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.
|
||||
|
||||
|
@ -234,12 +260,19 @@ class Rdata:
|
|||
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()
|
||||
|
@ -320,27 +353,39 @@ class Rdata:
|
|||
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
|
||||
|
||||
|
@ -348,15 +393,28 @@ class Rdata:
|
|||
return hash(self.to_digestable(dns.name.root))
|
||||
|
||||
@classmethod
|
||||
def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
|
||||
relativize_to=None):
|
||||
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, rdtype, parser, origin=None):
|
||||
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):
|
||||
def replace(self, **kwargs: Any) -> "Rdata":
|
||||
"""
|
||||
Create a new Rdata instance based on the instance replace was
|
||||
invoked on. It is possible to pass different parameters to
|
||||
|
@ -369,19 +427,25 @@ class Rdata:
|
|||
"""
|
||||
|
||||
# Get the constructor parameters.
|
||||
parameters = inspect.signature(self.__init__).parameters
|
||||
parameters = inspect.signature(self.__init__).parameters # type: ignore
|
||||
|
||||
# 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.
|
||||
|
@ -391,9 +455,9 @@ class Rdata:
|
|||
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
|
||||
|
@ -408,18 +472,26 @@ class Rdata:
|
|||
return dns.rdatatype.RdataType.make(value)
|
||||
|
||||
@classmethod
|
||||
def _as_bytes(cls, value, encode=False, max_length=None, empty_ok=True):
|
||||
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):
|
||||
value = value.encode()
|
||||
bvalue = value.encode()
|
||||
elif isinstance(value, bytearray):
|
||||
value = bytes(value)
|
||||
elif not isinstance(value, bytes):
|
||||
raise ValueError('not bytes')
|
||||
if max_length is not None and len(value) > max_length:
|
||||
raise ValueError('too long')
|
||||
if not empty_ok and len(value) == 0:
|
||||
raise ValueError('empty bytes not allowed')
|
||||
return value
|
||||
bvalue = bytes(value)
|
||||
elif isinstance(value, bytes):
|
||||
bvalue = value
|
||||
else:
|
||||
raise ValueError("not bytes")
|
||||
if max_length is not None and len(bvalue) > max_length:
|
||||
raise ValueError("too long")
|
||||
if not empty_ok and len(bvalue) == 0:
|
||||
raise ValueError("empty bytes not allowed")
|
||||
return bvalue
|
||||
|
||||
@classmethod
|
||||
def _as_name(cls, value):
|
||||
|
@ -429,49 +501,49 @@ class Rdata:
|
|||
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
|
||||
|
@ -483,7 +555,7 @@ class Rdata:
|
|||
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):
|
||||
|
@ -494,14 +566,14 @@ class Rdata:
|
|||
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):
|
||||
|
@ -510,7 +582,7 @@ class Rdata:
|
|||
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):
|
||||
|
@ -532,6 +604,7 @@ class Rdata:
|
|||
return items
|
||||
|
||||
|
||||
@dns.immutable.immutable
|
||||
class GenericRdata(Rdata):
|
||||
|
||||
"""Generic Rdata Class
|
||||
|
@ -540,28 +613,32 @@ 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)
|
||||
object.__setattr__(self, 'data', data)
|
||||
self.data = data
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
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):
|
||||
|
@ -571,8 +648,12 @@ class GenericRdata(Rdata):
|
|||
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
|
||||
return cls(rdclass, rdtype, parser.get_remaining())
|
||||
|
||||
_rdata_classes = {}
|
||||
_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))
|
||||
|
@ -581,16 +662,16 @@ def get_rdata_class(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
|
||||
|
@ -602,8 +683,15 @@ def get_rdata_class(rdclass, rdtype):
|
|||
return cls
|
||||
|
||||
|
||||
def from_text(rdclass, rdtype, tok, origin=None, relativize=True,
|
||||
relativize_to=None, idna_codec=None):
|
||||
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
|
||||
|
@ -617,9 +705,9 @@ def from_text(rdclass, rdtype, tok, origin=None, relativize=True,
|
|||
If *tok* is a ``str``, then a tokenizer is created and the string
|
||||
is used as its input.
|
||||
|
||||
*rdclass*, an ``int``, the rdataclass.
|
||||
*rdclass*, a ``dns.rdataclass.RdataClass`` or ``str``, the rdataclass.
|
||||
|
||||
*rdtype*, an ``int``, the rdatatype.
|
||||
*rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdatatype.
|
||||
|
||||
*tok*, a ``dns.tokenizer.Tokenizer`` or a ``str``.
|
||||
|
||||
|
@ -651,17 +739,18 @@ def from_text(rdclass, rdtype, tok, origin=None, relativize=True,
|
|||
# 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,
|
||||
|
@ -669,19 +758,27 @@ def from_text(rdclass, rdtype, tok, origin=None, relativize=True,
|
|||
#
|
||||
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, rdtype, parser, origin=None):
|
||||
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
|
||||
|
@ -692,9 +789,9 @@ def from_wire_parser(rdclass, rdtype, parser, origin=None):
|
|||
Once a class is chosen, its from_wire() class method is called
|
||||
with the parameters to this function.
|
||||
|
||||
*rdclass*, an ``int``, the rdataclass.
|
||||
*rdclass*, a ``dns.rdataclass.RdataClass`` or ``str``, the rdataclass.
|
||||
|
||||
*rdtype*, an ``int``, the rdatatype.
|
||||
*rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdatatype.
|
||||
|
||||
*parser*, a ``dns.wire.Parser``, the parser, which should be
|
||||
restricted to the rdata length.
|
||||
|
@ -712,7 +809,14 @@ def from_wire_parser(rdclass, rdtype, parser, origin=None):
|
|||
return cls.from_wire_parser(rdclass, rdtype, parser, origin)
|
||||
|
||||
|
||||
def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None):
|
||||
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
|
||||
|
@ -746,13 +850,21 @@ def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None):
|
|||
|
||||
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, rdtype, rdtype_text, is_singleton=False,
|
||||
rdclass=dns.rdataclass.IN):
|
||||
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
|
||||
|
@ -769,14 +881,16 @@ def register_type(implementation, rdtype, rdtype_text, is_singleton=False,
|
|||
it applies to all classes.
|
||||
"""
|
||||
|
||||
existing_cls = get_rdata_class(rdclass, rdtype)
|
||||
if existing_cls != GenericRdata or dns.rdatatype.is_metatype(rdtype):
|
||||
raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype)
|
||||
the_rdtype = dns.rdatatype.RdataType.make(rdtype)
|
||||
existing_cls = get_rdata_class(rdclass, the_rdtype)
|
||||
if existing_cls != GenericRdata or dns.rdatatype.is_metatype(the_rdtype):
|
||||
raise RdatatypeExists(rdclass=rdclass, rdtype=the_rdtype)
|
||||
try:
|
||||
if dns.rdatatype.RdataType(rdtype).name != rdtype_text:
|
||||
raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype)
|
||||
if dns.rdatatype.RdataType(the_rdtype).name != rdtype_text:
|
||||
raise RdatatypeExists(rdclass=rdclass, rdtype=the_rdtype)
|
||||
except ValueError:
|
||||
pass
|
||||
_rdata_classes[(rdclass, rdtype)] = getattr(implementation,
|
||||
rdtype_text.replace('-', '_'))
|
||||
dns.rdatatype.register_type(rdtype, rdtype_text, is_singleton)
|
||||
_rdata_classes[(rdclass, the_rdtype)] = getattr(
|
||||
implementation, rdtype_text.replace("-", "_")
|
||||
)
|
||||
dns.rdatatype.register_type(the_rdtype, rdtype_text, is_singleton)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue