]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Add dns.edns.Option.to_generic() (#1145)
authorBrian Wellington <bwelling@xbill.org>
Fri, 11 Oct 2024 20:34:57 +0000 (13:34 -0700)
committerGitHub <noreply@github.com>
Fri, 11 Oct 2024 20:34:57 +0000 (13:34 -0700)
* Add dns.edns.Option.to_generic()

Converts an EDNS option represented by a custom class into an equivalent
option represented by the generic option class.  This is similar to the
existing dns.rdata.Rdata.to_generic() method.

Also, adds a specialization to the existing dns.rdata.Rdata.to_generic()
method for GenericRdata, to avoid extra work for applications that want
to convert all rdata to generic form.

* Fix typing issue.

* Fix typing again.

dns/edns.py
dns/rdata.py
tests/test_edns.py
tests/test_rdata.py

index f7d9ff996b5ac4e68798c67d2c8c96195d0a5dad..c36036864c5a2850b9fd5dcde8792a211c5acca6 100644 (file)
@@ -81,6 +81,15 @@ class Option:
     def to_text(self) -> str:
         raise NotImplementedError  # pragma: no cover
 
+    def to_generic(self) -> "dns.edns.GenericOption":
+        """Creates a dns.edns.GenericOption equivalent of this rdata.
+
+        Returns a ``dns.edns.GenericOption``.
+        """
+        wire = self.to_wire()
+        assert wire is not None  # for mypy
+        return dns.edns.GenericOption(self.otype, wire)
+
     @classmethod
     def from_wire_parser(cls, otype: OptionType, parser: "dns.wire.Parser") -> "Option":
         """Build an EDNS option object from wire format.
@@ -166,6 +175,9 @@ class GenericOption(Option):  # lgtm[py/missing-equals]
     def to_text(self) -> str:
         return "Generic %d" % self.otype
 
+    def to_generic(self) -> "dns.edns.GenericOption":
+        return self
+
     @classmethod
     def from_wire_parser(
         cls, otype: Union[OptionType, str], parser: "dns.wire.Parser"
index 8099c26aab9029b454a8709575d6f1fd7aba108d..0189f240966d47e4a8c31fd6673ecaa434b0641a 100644 (file)
@@ -639,6 +639,11 @@ class GenericRdata(Rdata):
     def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.data)
 
+    def to_generic(
+        self, origin: Optional[dns.name.Name] = None
+    ) -> "dns.rdata.GenericRdata":
+        return self
+
     @classmethod
     def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
         return cls(rdclass, rdtype, parser.get_remaining())
index 952ca05ecfb777abdb597d59543e76352ff66a02..1229c1e9c7f0beb96dd8c09b8ea89c996ca91191 100644 (file)
@@ -302,3 +302,13 @@ class OptionTestCase(unittest.TestCase):
 
         opt = dns.edns.option_from_wire_parser(9999, dns.wire.Parser(wire1))
         self.assertEqual(opt, generic)
+
+    def test_to_generic(self):
+        nsid = dns.edns.NSIDOption(b"testing")
+        assert nsid.to_generic().data == b"testing"
+
+        ecs = dns.edns.ECSOption("1.2.3.0", 24)
+        assert ecs.to_generic().data == b"\x00\x01\x18\x00\x01\x02\x03"
+
+        generic = dns.edns.GenericOption(12345, "foo")
+        assert generic.to_generic() is generic
index c63dc18c7ac3ce01a5197835c78b426026cab79f..4c62aa1d4c25b812301bb366e6ea91ea0900c6d3 100644 (file)
@@ -130,6 +130,9 @@ class RdataTestCase(unittest.TestCase):
             str(ns.to_generic(origin=origin)), r"\# 13 03666f6f076578616d706c6500"
         )
 
+        generic = dns.rdata.from_text("in", "type45678", "\\# 4 00010203")
+        assert generic.to_generic() is generic
+
     def test_txt_unicode(self):
         # TXT records are not defined for Unicode, but if we get
         # Unicode we should convert it to UTF-8 to preserve meaning as