diff --git a/CHANGELOG.md b/CHANGELOG.md index 08e6ab0..1a36082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ changes/fixes on the first sync after updating IFF you currently have `values: a-single-thing`, which would have previously been pushed up as bunch of single character values. +* Record.octodns added to formally make that data "API" and Record._octodns is + deprecated. The latter has been converted to properties that return the + former and emit deprecation warnings. ## v1.4.0 - 2023-12-04 - Minor Meta diff --git a/octodns/record/base.py b/octodns/record/base.py index 058b12d..456473c 100644 --- a/octodns/record/base.py +++ b/octodns/record/base.py @@ -7,6 +7,7 @@ from copy import deepcopy from logging import getLogger from ..context import ContextDict +from ..deprecation import deprecated from ..equality import EqualityTupleMixin from ..idna import IdnaError, idna_decode, idna_encode from .change import Update @@ -165,12 +166,28 @@ class Record(EqualityTupleMixin): self.context = context self.ttl = int(data['ttl']) - self._octodns = data.get('octodns', {}) + self.octodns = data.get('octodns', {}) + + @property + def _octodns(self): + deprecated( + '`Record._octodns` is DEPRECATED. Use `Record.octodns` instead. Will be removed in 2.0', + stacklevel=1, + ) + return self.octodns + + @_octodns.setter + def _octodns(self, val): + deprecated( + '`Record._octodns` is DEPRECATED. Use `Record.octodns` instead. Will be removed in 2.0', + stacklevel=1, + ) + self.octodns = val def _data(self): ret = {'ttl': self.ttl} - if self._octodns: - ret['octodns'] = deepcopy(self._octodns) + if self.octodns: + ret['octodns'] = deepcopy(self.octodns) if self.context: return ContextDict(ret, context=self.context) return ret @@ -195,25 +212,25 @@ class Record(EqualityTupleMixin): @property def ignored(self): - return self._octodns.get('ignored', False) + return self.octodns.get('ignored', False) @property def excluded(self): - return self._octodns.get('excluded', []) + return self.octodns.get('excluded', []) @property def included(self): - return self._octodns.get('included', []) + return self.octodns.get('included', []) def healthcheck_host(self, value=None): - healthcheck = self._octodns.get('healthcheck', {}) + healthcheck = self.octodns.get('healthcheck', {}) if healthcheck.get('protocol', None) == 'TCP': return None return healthcheck.get('host', self.fqdn[:-1]) or value @property def healthcheck_path(self): - healthcheck = self._octodns.get('healthcheck', {}) + healthcheck = self.octodns.get('healthcheck', {}) if healthcheck.get('protocol', None) == 'TCP': return None try: @@ -224,20 +241,20 @@ class Record(EqualityTupleMixin): @property def healthcheck_protocol(self): try: - return self._octodns['healthcheck']['protocol'] + return self.octodns['healthcheck']['protocol'] except KeyError: return 'HTTPS' @property def healthcheck_port(self): try: - return int(self._octodns['healthcheck']['port']) + return int(self.octodns['healthcheck']['port']) except KeyError: return 443 @property def lenient(self): - return self._octodns.get('lenient', False) + return self.octodns.get('lenient', False) def changes(self, other, target): # We're assuming we have the same name and type if we're being compared @@ -336,8 +353,8 @@ class ValuesMixin(object): values = "', '".join([str(v) for v in self.values]) klass = self.__class__.__name__ octodns = '' - if self._octodns: - octodns = f', {self._octodns}' + if self.octodns: + octodns = f', {self.octodns}' return f"<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, ['{values}']{octodns}>" @@ -381,6 +398,6 @@ class ValueMixin(object): def __repr__(self): klass = self.__class__.__name__ octodns = '' - if self._octodns: - octodns = f', {self._octodns}' + if self.octodns: + octodns = f', {self.octodns}' return f'<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, {self.value}{octodns}>' diff --git a/tests/test_octodns_provider_yaml.py b/tests/test_octodns_provider_yaml.py index b98c067..06a6466 100644 --- a/tests/test_octodns_provider_yaml.py +++ b/tests/test_octodns_provider_yaml.py @@ -86,7 +86,7 @@ class TestYamlProvider(TestCase): {'included': ['test']}, [x for x in reloaded.records if x.name == 'included'][ 0 - ]._octodns, + ].octodns, ) # manually copy over the root since it will have been ignored @@ -577,7 +577,7 @@ class TestSplitYamlProvider(TestCase): {'included': ['test']}, [x for x in reloaded.records if x.name == 'included'][ 0 - ]._octodns, + ].octodns, ) # manually copy over the root since it will have been ignored diff --git a/tests/test_octodns_record.py b/tests/test_octodns_record.py index 8cbfa5a..235fead 100644 --- a/tests/test_octodns_record.py +++ b/tests/test_octodns_record.py @@ -323,33 +323,33 @@ class TestRecord(TestCase): # hand add something at the first level of the copy b = a.copy() - b._octodns['added'] = 'thing' + b.octodns['added'] = 'thing' b_data = b.data self.assertNotEqual(a.data, b_data) # hand modify something at the first level of the copy b = a.copy() - b._octodns['first'] = 'unlevel' + b.octodns['first'] = 'unlevel' self.assertNotEqual(a.data, b.data) # delete something at the first level of the copy b = a.copy() - del b._octodns['first'] + del b.octodns['first'] self.assertNotEqual(a.data, b.data) # hand add something deeper in the copy b = a.copy() - b._octodns['key']['added'] = 'thing' + b.octodns['key']['added'] = 'thing' self.assertNotEqual(a.data, b.data) # hand modify something deeper in the copy b = a.copy() - b._octodns['key']['second'] = 'unlevel' + b.octodns['key']['second'] = 'unlevel' self.assertNotEqual(a.data, b.data) # hand delete something deeper in the copy b = a.copy() - del b._octodns['key']['second'] + del b.octodns['key']['second'] self.assertNotEqual(a.data, b.data) def test_record_copy_with_no_values(self): @@ -519,6 +519,26 @@ class TestRecord(TestCase): self.assertEqual(None, unquote(None)) self.assertEqual('', unquote('')) + def test_otodns_backcompat(self): + octo = {'answer': 42} + record = Record.new( + self.zone, + 'www', + {'ttl': 42, 'type': 'A', 'value': '1.2.3.4', 'octodns': octo}, + ) + self.assertEqual(octo, record.octodns) + self.assertEqual(octo, record._octodns) + + octo2 = {'question': 'unknown'} + record.octodns = octo2 + self.assertEqual(octo2, record.octodns) + self.assertEqual(octo2, record._octodns) + + octo3 = {'key': 'val'} + record._octodns = octo3 + self.assertEqual(octo3, record.octodns) + self.assertEqual(octo3, record._octodns) + class TestRecordValidation(TestCase): zone = Zone('unit.tests.', []) @@ -817,7 +837,7 @@ class TestRecordValidation(TestCase): record.__repr__(), ) # no special section - record._octodns = {} + record.octodns = {} self.assertEqual( "", record.__repr__(), @@ -841,7 +861,7 @@ class TestRecordValidation(TestCase): record.__repr__(), ) # no special section - record._octodns = {} + record.octodns = {} self.assertEqual( '', record.__repr__(), diff --git a/tests/test_octodns_record_dynamic.py b/tests/test_octodns_record_dynamic.py index 22fe911..8d7b402 100644 --- a/tests/test_octodns_record_dynamic.py +++ b/tests/test_octodns_record_dynamic.py @@ -37,7 +37,7 @@ class TestRecordDynamic(TestCase): } record1 = Record.new(self.zone, 'a', a_data) record2 = record1.copy() - self.assertEqual(record1._octodns, record2._octodns) + self.assertEqual(record1.octodns, record2.octodns) def test_healthcheck(self): new = Record.new(