diff --git a/octodns/record/__init__.py b/octodns/record/__init__.py index 8f16484..bd65b06 100644 --- a/octodns/record/__init__.py +++ b/octodns/record/__init__.py @@ -3,34 +3,29 @@ # +from .a import ARecord, Ipv4Address, Ipv4Value +from .aaaa import AaaaRecord, Ipv6Address, Ipv6Value +from .alias import AliasRecord, AliasValue from .base import Record, ValueMixin, ValuesMixin -from .change import Change, Create, Delete, Update from .caa import CaaRecord, CaaValue +from .change import Change, Create, Delete, Update +from .cname import CnameRecord, CnameValue +from .dname import DnameRecord, DnameValue from .ds import DsRecord, DsValue from .exception import RecordException, ValidationError from .geo import GeoCodes, GeoValue from .loc import LocRecord, LocValue from .mx import MxRecord, MxValue from .naptr import NaptrRecord, NaptrValue +from .ns import NsValue, NsRecord +from .ptr import PtrValue, PtrRecord from .rr import Rr, RrParseError -from .tlsa import TlsaRecord, TlsaValue -from .url import UrlfwdRecord, UrlfwdValue +from .spf import SpfRecord from .srv import SrvRecord, SrvValue from .sshfp import SshfpRecord, SshfpValue -from .target import ( - AliasRecord, - AliasValue, - CnameRecord, - CnameValue, - DnameRecord, - DnameValue, - NsValue, - NsRecord, - PtrValue, - PtrRecord, -) -from .ipaddress import ARecord, AaaaRecord, Ipv4Address, Ipv6Address -from .chunked import SpfRecord, TxtValue, TxtRecord +from .tlsa import TlsaRecord, TlsaValue +from .txt import TxtValue, TxtRecord +from .url import UrlfwdRecord, UrlfwdValue # quell warnings ARecord @@ -51,7 +46,9 @@ DsValue GeoCodes GeoValue Ipv4Address +Ipv4Value Ipv6Address +Ipv6Value LocRecord LocValue MxRecord diff --git a/octodns/record/a.py b/octodns/record/a.py new file mode 100644 index 0000000..313f53c --- /dev/null +++ b/octodns/record/a.py @@ -0,0 +1,26 @@ +# +# +# + +from ipaddress import IPv4Address as _IPv4Address + +from .base import Record +from .dynamic import _DynamicMixin +from .geo import _GeoMixin +from .ip import _IpValue + + +class Ipv4Value(_IpValue): + _address_type = _IPv4Address + _address_name = 'IPv4' + + +Ipv4Address = Ipv4Value + + +class ARecord(_DynamicMixin, _GeoMixin, Record): + _type = 'A' + _value_type = Ipv4Value + + +Record.register_type(ARecord) diff --git a/octodns/record/aaaa.py b/octodns/record/aaaa.py new file mode 100644 index 0000000..3d0a3e4 --- /dev/null +++ b/octodns/record/aaaa.py @@ -0,0 +1,26 @@ +# +# +# + +from ipaddress import IPv6Address as _IPv6Address + +from .base import Record +from .dynamic import _DynamicMixin +from .geo import _GeoMixin +from .ip import _IpValue + + +class Ipv6Value(_IpValue): + _address_type = _IPv6Address + _address_name = 'IPv6' + + +Ipv6Address = Ipv6Value + + +class AaaaRecord(_DynamicMixin, _GeoMixin, Record): + _type = 'AAAA' + _value_type = Ipv6Address + + +Record.register_type(AaaaRecord) diff --git a/octodns/record/alias.py b/octodns/record/alias.py new file mode 100644 index 0000000..4802591 --- /dev/null +++ b/octodns/record/alias.py @@ -0,0 +1,26 @@ +# +# +# + +from .base import Record, ValueMixin +from .target import _TargetValue + + +class AliasValue(_TargetValue): + pass + + +class AliasRecord(ValueMixin, Record): + _type = 'ALIAS' + _value_type = AliasValue + + @classmethod + def validate(cls, name, fqdn, data): + reasons = [] + if name != '': + reasons.append('non-root ALIAS not allowed') + reasons.extend(super().validate(name, fqdn, data)) + return reasons + + +Record.register_type(AliasRecord) diff --git a/octodns/record/chunked.py b/octodns/record/chunked.py index d944342..8f8009e 100644 --- a/octodns/record/chunked.py +++ b/octodns/record/chunked.py @@ -2,7 +2,7 @@ # # -from .base import Record, ValuesMixin +from .base import ValuesMixin import re @@ -61,23 +61,3 @@ class _ChunkedValue(str): @property def rdata_text(self): return self - - -class SpfRecord(_ChunkedValuesMixin, Record): - _type = 'SPF' - _value_type = _ChunkedValue - - -Record.register_type(SpfRecord) - - -class TxtValue(_ChunkedValue): - pass - - -class TxtRecord(_ChunkedValuesMixin, Record): - _type = 'TXT' - _value_type = TxtValue - - -Record.register_type(TxtRecord) diff --git a/octodns/record/cname.py b/octodns/record/cname.py new file mode 100644 index 0000000..268bda7 --- /dev/null +++ b/octodns/record/cname.py @@ -0,0 +1,27 @@ +# +# +# + +from .base import Record, ValueMixin +from .dynamic import _DynamicMixin +from .target import _TargetValue + + +class CnameValue(_TargetValue): + pass + + +class CnameRecord(_DynamicMixin, ValueMixin, Record): + _type = 'CNAME' + _value_type = CnameValue + + @classmethod + def validate(cls, name, fqdn, data): + reasons = [] + if name == '': + reasons.append('root CNAME not allowed') + reasons.extend(super().validate(name, fqdn, data)) + return reasons + + +Record.register_type(CnameRecord) diff --git a/octodns/record/dname.py b/octodns/record/dname.py new file mode 100644 index 0000000..43a4b9e --- /dev/null +++ b/octodns/record/dname.py @@ -0,0 +1,19 @@ +# +# +# + +from .base import Record, ValueMixin +from .dynamic import _DynamicMixin +from .target import _TargetValue + + +class DnameValue(_TargetValue): + pass + + +class DnameRecord(_DynamicMixin, ValueMixin, Record): + _type = 'DNAME' + _value_type = DnameValue + + +Record.register_type(DnameRecord) diff --git a/octodns/record/ipaddress.py b/octodns/record/ip.py similarity index 67% rename from octodns/record/ipaddress.py rename to octodns/record/ip.py index 3c2a44a..6b3fe3c 100644 --- a/octodns/record/ipaddress.py +++ b/octodns/record/ip.py @@ -2,14 +2,8 @@ # # -from ipaddress import IPv4Address as _IPv4Address, IPv6Address as _IPv6Address -from .base import Record -from .dynamic import _DynamicMixin -from .geo import _GeoMixin - - -class _IpAddress(str): +class _IpValue(str): @classmethod def parse_rdata_text(cls, value): return value @@ -52,27 +46,4 @@ class _IpAddress(str): return self -class Ipv4Address(_IpAddress): - _address_type = _IPv4Address - _address_name = 'IPv4' - - -class ARecord(_DynamicMixin, _GeoMixin, Record): - _type = 'A' - _value_type = Ipv4Address - - -Record.register_type(ARecord) - - -class Ipv6Address(_IpAddress): - _address_type = _IPv6Address - _address_name = 'IPv6' - - -class AaaaRecord(_DynamicMixin, _GeoMixin, Record): - _type = 'AAAA' - _value_type = Ipv6Address - - -Record.register_type(AaaaRecord) +_IpAddress = _IpValue diff --git a/octodns/record/ns.py b/octodns/record/ns.py new file mode 100644 index 0000000..1b7895e --- /dev/null +++ b/octodns/record/ns.py @@ -0,0 +1,18 @@ +# +# +# + +from .base import Record, ValuesMixin +from .target import _TargetsValue + + +class NsValue(_TargetsValue): + pass + + +class NsRecord(ValuesMixin, Record): + _type = 'NS' + _value_type = NsValue + + +Record.register_type(NsRecord) diff --git a/octodns/record/ptr.py b/octodns/record/ptr.py new file mode 100644 index 0000000..6cecb06 --- /dev/null +++ b/octodns/record/ptr.py @@ -0,0 +1,24 @@ +# +# +# + +from .base import Record, ValuesMixin +from .target import _TargetsValue + + +class PtrValue(_TargetsValue): + pass + + +class PtrRecord(ValuesMixin, Record): + _type = 'PTR' + _value_type = PtrValue + + # This is for backward compatibility with providers that don't support + # multi-value PTR records. + @property + def value(self): + return self.values[0] + + +Record.register_type(PtrRecord) diff --git a/octodns/record/spf.py b/octodns/record/spf.py new file mode 100644 index 0000000..ac59c57 --- /dev/null +++ b/octodns/record/spf.py @@ -0,0 +1,14 @@ +# +# +# + +from .base import Record +from .chunked import _ChunkedValue, _ChunkedValuesMixin + + +class SpfRecord(_ChunkedValuesMixin, Record): + _type = 'SPF' + _value_type = _ChunkedValue + + +Record.register_type(SpfRecord) diff --git a/octodns/record/target.py b/octodns/record/target.py index 31e23cb..f9dbc18 100644 --- a/octodns/record/target.py +++ b/octodns/record/target.py @@ -5,8 +5,6 @@ from fqdn import FQDN from ..idna import idna_encode -from .base import Record, ValueMixin, ValuesMixin -from .dynamic import _DynamicMixin class _TargetValue(str): @@ -79,85 +77,3 @@ class _TargetsValue(str): @property def rdata_text(self): return self - - -class AliasValue(_TargetValue): - pass - - -class AliasRecord(ValueMixin, Record): - _type = 'ALIAS' - _value_type = AliasValue - - @classmethod - def validate(cls, name, fqdn, data): - reasons = [] - if name != '': - reasons.append('non-root ALIAS not allowed') - reasons.extend(super().validate(name, fqdn, data)) - return reasons - - -Record.register_type(AliasRecord) - - -class CnameValue(_TargetValue): - pass - - -class CnameRecord(_DynamicMixin, ValueMixin, Record): - _type = 'CNAME' - _value_type = CnameValue - - @classmethod - def validate(cls, name, fqdn, data): - reasons = [] - if name == '': - reasons.append('root CNAME not allowed') - reasons.extend(super().validate(name, fqdn, data)) - return reasons - - -Record.register_type(CnameRecord) - - -class DnameValue(_TargetValue): - pass - - -class DnameRecord(_DynamicMixin, ValueMixin, Record): - _type = 'DNAME' - _value_type = DnameValue - - -Record.register_type(DnameRecord) - - -class NsValue(_TargetsValue): - pass - - -class NsRecord(ValuesMixin, Record): - _type = 'NS' - _value_type = NsValue - - -Record.register_type(NsRecord) - - -class PtrValue(_TargetsValue): - pass - - -class PtrRecord(ValuesMixin, Record): - _type = 'PTR' - _value_type = PtrValue - - # This is for backward compatibility with providers that don't support - # multi-value PTR records. - @property - def value(self): - return self.values[0] - - -Record.register_type(PtrRecord) diff --git a/octodns/record/txt.py b/octodns/record/txt.py new file mode 100644 index 0000000..addc501 --- /dev/null +++ b/octodns/record/txt.py @@ -0,0 +1,18 @@ +# +# +# + +from .base import Record +from .chunked import _ChunkedValue, _ChunkedValuesMixin + + +class TxtValue(_ChunkedValue): + pass + + +class TxtRecord(_ChunkedValuesMixin, Record): + _type = 'TXT' + _value_type = TxtValue + + +Record.register_type(TxtRecord) diff --git a/tests/test_octodns_record.py b/tests/test_octodns_record.py index c5dcb1d..320152d 100644 --- a/tests/test_octodns_record.py +++ b/tests/test_octodns_record.py @@ -62,7 +62,7 @@ class TestRecord(TestCase): with self.assertRaises(RecordException) as ctx: Record.register_type(None, 'A') self.assertEqual( - 'Type "A" already registered by octodns.record.ipaddress.ARecord', + 'Type "A" already registered by octodns.record.a.ARecord', str(ctx.exception), )