]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Clean up imports of dnspython modules
authorŠtěpán Balážik <stepan@isc.org>
Mon, 9 Feb 2026 18:22:44 +0000 (19:22 +0100)
committerŠtěpán Balážik <stepan@isc.org>
Fri, 20 Feb 2026 14:17:32 +0000 (15:17 +0100)
Add a pylint plugin that enforces:
  - There is no bare `import dns` statement.
  - All `dns.<module>` used are explicitly imported.
  - There are no unused `dns.<module>` imports.

Fix all the imports to conform with this check.

50 files changed:
bin/tests/system/bailiwick/tests_bailiwick.py
bin/tests/system/checkds/tests_checkds.py
bin/tests/system/cipher-suites/tests_cipher_suites.py
bin/tests/system/database/tests_database.py
bin/tests/system/digdelv/ans7/ans.py
bin/tests/system/dns_import_checker.py [new file with mode: 0644]
bin/tests/system/dnssec-malformed-dnskey/tests_malformed_dnskey.py
bin/tests/system/dnstap/tests_dnstap.py
bin/tests/system/doth/tests_gnutls.py
bin/tests/system/filters/common.py
bin/tests/system/filters/tests_filter_aaaa_v4.py
bin/tests/system/glue/tests_glue.py
bin/tests/system/hooks/tests_hooks.py
bin/tests/system/isctest/asyncserver.py
bin/tests/system/isctest/check.py
bin/tests/system/isctest/hypothesis/strategies.py
bin/tests/system/isctest/instance.py
bin/tests/system/isctest/kasp.py
bin/tests/system/isctest/query.py
bin/tests/system/isctest/util.py
bin/tests/system/kasp/tests_kasp.py
bin/tests/system/limits/tests_limits.py
bin/tests/system/migrate2kasp/tests_migrate2kasp.py
bin/tests/system/multisigner/tests_multisigner.py
bin/tests/system/nsec3-answer/tests_nsec3.py
bin/tests/system/nsec3/common.py
bin/tests/system/nsec3/tests_nsec3_change.py
bin/tests/system/nsec3/tests_nsec3_initial.py
bin/tests/system/nsec3/tests_nsec3_reconfig.py
bin/tests/system/nsec3/tests_nsec3_restart.py
bin/tests/system/nsec3/tests_nsec3_retransfer.py
bin/tests/system/optout/tests_optout.py
bin/tests/system/qmin/ans2/ans.py
bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py
bin/tests/system/rpzextra/tests_rpzextra.py
bin/tests/system/selftest/tests_zone_analyzer.py
bin/tests/system/showconf/tests_showconf.py
bin/tests/system/shutdown/tests_shutdown.py
bin/tests/system/statschannel/generic.py
bin/tests/system/stress/tests_stress_update.py
bin/tests/system/stub/tests_stub.py
bin/tests/system/synthrecord/tests_synthrecord.py
bin/tests/system/tcp/tests_tcp.py
bin/tests/system/timeouts/tests_tcp_timeouts.py
bin/tests/system/tsig/tests_badtime.py
bin/tests/system/tsiggss/tests_isc_spnego_flaws.py
bin/tests/system/wildcard/tests_wildcard.py
bin/tests/system/xfer/tests_xfer.py
bin/tests/system/xferquota/tests_xferquota.py
pyproject.toml

index 3fc647992df9cc328dd17966cde0ccd18dd26af3..8456cc6f514b8884e21de3c7d3e076fa322cd6cd 100644 (file)
@@ -13,6 +13,7 @@
 import time
 
 import dns.message
+import dns.rrset
 import pytest
 
 from isctest.instance import NamedInstance
index 245ed5bf6234fe362c8e2ad2b76dacf8287e8df7..c0f834c42ba27783853c54a66b1f7c01210dfedb 100755 (executable)
@@ -18,8 +18,6 @@ import os
 import sys
 import time
 
-import dns.exception
-import dns.message
 import dns.name
 import dns.rcode
 import dns.rdataclass
index 94d0f255b79f42e947426950936601fabbd4e1a8..c20401bbce04cf598c2c199cfb81aa78cbe87b81 100644 (file)
@@ -11,7 +11,7 @@
 
 from re import compile as Re
 
-import dns.message
+import dns.rcode
 import pytest
 
 import isctest
index 89f818e9aa1ca0c4813ee863b9572cadb4d25a73..8e4a0e7ae45ab29c7a669b1b73e3fc9f5059d782 100644 (file)
@@ -9,7 +9,8 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
-import dns
+
+import dns.rrset
 
 import isctest
 
index 768c01e2249e1d0cf6e0a85492d7a48f4e7ed8e1..0dde43c6a801b3e74ceaf9656cfc4ff544e7360a 100644 (file)
@@ -11,7 +11,6 @@
 
 from typing import AsyncGenerator
 
-import dns
 import dns.rcode
 
 from isctest.asyncserver import (
diff --git a/bin/tests/system/dns_import_checker.py b/bin/tests/system/dns_import_checker.py
new file mode 100644 (file)
index 0000000..0af3252
--- /dev/null
@@ -0,0 +1,177 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from pylint.checkers import BaseChecker
+
+import astroid
+
+
+class DnsExplicitImportsChecker(BaseChecker):
+    name = "dns-explicit-imports"
+
+    msgs = {
+        "W9001": (
+            "Bare 'import dns' is discouraged; import required submodules explicitly",
+            "dns-bare-import",
+            "Emitted when the package root 'dns' is imported directly.",
+        ),
+        "W9002": (
+            "Missing explicit import for '%s' (add `import %s`)",
+            "dns-missing-submodule-import",
+            "Emitted when code references dns.<...> but the corresponding module prefix "
+            "was not imported with `import dns.<...>`.",
+        ),
+        "W9003": (
+            "Unused explicit import for '%s' (remove `import %s`)",
+            "dns-unused-submodule-import",
+            "Emitted when a dns.<...> module is imported explicitly but not used.",
+        ),
+    }
+
+    def __init__(self, linter=None):
+        super().__init__(linter)
+        self._imported = {}
+        self._imported_aliases = set()
+        self._required = {}
+
+    def visit_module(self, node):  # pylint: disable=unused-argument
+        self._imported = {}
+        self._imported_aliases = set()
+        self._required = {}
+
+    def leave_module(self, node):  # pylint: disable=unused-argument
+        for mod, use_node in sorted(self._required.items()):
+            if mod in self._imported:
+                continue
+            prefix = mod + "."
+            if any(name.startswith(prefix) for name in self._imported):
+                continue
+            self.add_message(
+                "dns-missing-submodule-import",
+                node=use_node,
+                args=(mod, mod),
+            )
+        for mod, import_node in sorted(self._imported.items()):
+            if mod in self._imported_aliases:
+                continue
+            if any(
+                name == mod or name.startswith(mod + ".") for name in self._required
+            ):
+                continue
+            self.add_message(
+                "dns-unused-submodule-import",
+                node=import_node,
+                args=(mod, mod),
+            )
+
+    def visit_import(self, node):
+        for name, _asname in node.names:
+            if name == "dns":
+                self.add_message("dns-bare-import", node=node)
+                continue
+            if name.startswith("dns."):
+                self._imported.setdefault(name, node)
+                if _asname:
+                    self._imported_aliases.add(name)
+
+    def visit_importfrom(self, node):  # pylint: disable=unused-argument
+        return
+
+    def visit_attribute(self, node):
+        parent = node.parent
+        # For `dns.a.b.c`, astroid visits intermediate attributes too.
+        # Process only the rightmost node to avoid duplicate bookkeeping.
+        if isinstance(parent, astroid.nodes.Attribute) and parent.expr is node:
+            return
+
+        mod = self._dns_module_for_attribute(node)
+        if mod is None:
+            return
+
+        self._required.setdefault(mod, node)
+
+    @staticmethod
+    def _dns_attribute_nodes(node):
+        """
+        Return the chain of Attribute nodes as a list.
+
+        For `dns.a.b.c`, return the list of Attribute nodes for `dns.a`, `dns.a.b`, and `dns.a.b.c`.
+
+        Return None if the chain is not rooted in `dns`.
+        """
+
+        if not isinstance(node, astroid.nodes.Attribute):
+            return None
+
+        nodes = []
+        expr = node
+        while isinstance(expr, astroid.nodes.Attribute):
+            nodes.append(expr)
+            expr = expr.expr
+
+        if not isinstance(expr, astroid.nodes.Name) or expr.name != "dns":
+            return None
+
+        return list(reversed(nodes))
+
+    @classmethod
+    def _dns_module_for_attribute(cls, node):
+        """
+        For dns.a.b.c, return the longest dns.a.b... prefix that is likely to be a module,
+        or None if the chain is not rooted in dns.
+        """
+        last_module = None
+        chain_nodes = cls._dns_attribute_nodes(node)
+        if chain_nodes is None:
+            return None
+
+        full = "dns." + ".".join(part.attrname for part in chain_nodes)
+        # Prefer inferred module names to avoid treating classes/constants as
+        # modules (e.g. `dns.name.NameRelation` should resolve to `dns.name`).
+        for chain_node in chain_nodes:
+            inferred = cls._infer_module_name(chain_node)
+            if inferred is not None and full.startswith(inferred):
+                last_module = inferred
+        if last_module is not None:
+            return last_module
+
+        # Fallback when inference is unavailable: assume the terminal segment
+        # is not a module symbol and require the parent path.
+        parts = full.split(".")
+        if len(parts) <= 2:
+            return full
+        return ".".join(parts[:-1])
+
+    @staticmethod
+    def _infer_module_name(node):
+        """Infer `dns.<module>` for a node; return None if inference is unsure."""
+        try:
+            for inferred in node.infer():
+                if inferred is astroid.util.Uninferable:
+                    continue
+                # Inference can return either a Module node directly or another
+                # symbol rooted in a module; normalize both to module name.
+                module = (
+                    inferred
+                    if isinstance(inferred, astroid.nodes.Module)
+                    else inferred.root()
+                )
+                name = module.name
+                if name.startswith("dns."):
+                    return name
+        # Inference can fail for dynamic/partial code; fall back gracefully.
+        except astroid.AstroidError:
+            pass
+        return None
+
+
+def register(linter):
+    linter.register_checker(DnsExplicitImportsChecker(linter))
index efb5839ddc6c205b0a0baef7bbdf08939a862f54..cdb8932e7cdac16491225f23acecec8a2d555e56 100644 (file)
@@ -17,8 +17,11 @@ import os
 from cryptography.hazmat.primitives.asymmetric import ec
 from dns.rdtypes.dnskeybase import Flag
 
-import dns
 import dns.dnssec
+import dns.name
+import dns.rdataclass
+import dns.rdatatype
+import dns.rdtypes.ANY.RRSIG
 import dns.zone
 import pytest
 
index 9004c45e834fb5677256287c041b5027460cbdbe..1ec4cc17cf5316b5ae6188034df3b79c25d22fcd 100644 (file)
@@ -14,6 +14,7 @@
 import os
 import re
 
+import dns.rcode
 import dns.rrset
 import pytest
 
index 16ecdb5073aa166d3c4a71b3d093a7fa7d98bbdb..7053311debdc8994f90176da257c4729c84187fe 100644 (file)
@@ -16,8 +16,8 @@ import struct
 import subprocess
 import time
 
-import dns
 import dns.exception
+import dns.message
 import dns.name
 import dns.rdataclass
 import dns.rdatatype
index 6db8f197564069c03ba727e71e72546cbdf4a0fd..12542a9ab6041f585915029d3f5195535ec3e032 100644 (file)
@@ -11,7 +11,7 @@
 
 from dns import rdataclass, rdatatype
 
-import dns
+import dns.name
 
 import isctest
 
index adf46add049d39d75e044ae5493783ca5a231ea9..7f5e612865b9444905f1639c298453493cf7b05d 100644 (file)
@@ -18,7 +18,6 @@ from filters.common import (
     prime_cache,
 )
 
-import isctest
 import isctest.mark
 
 pytestmark = pytest.mark.extra_artifacts(ARTIFACTS)
index 93b0164c39bc46c48eaaabf0baa78f32f71e2884..4b08515535d5a1e62d4bd29f72df30aee1016cd8 100644 (file)
@@ -10,6 +10,7 @@
 # information regarding copyright ownership.
 
 
+import dns.edns
 import dns.flags
 import dns.message
 import pytest
index 75305e9b353629d56c9d04044ed0c66b6d9ace57..247ac9a10b8e16db3cc3a53c8ce1c10e72d32143 100644 (file)
@@ -13,7 +13,7 @@ import glob
 import os
 import subprocess
 
-import dns
+import dns.rcode
 import pytest
 
 import isctest
index 0dfc19b1196b467ecfb293bca499880a63f720d4..453751629f0217875e2d795ff6511067f8732550 100644 (file)
@@ -40,7 +40,6 @@ import dns.rdataset
 import dns.rdatatype
 import dns.rrset
 import dns.tsig
-import dns.version
 import dns.zone
 
 _UdpHandler = Callable[
index c7e89a217c0a20c4120d785f210d90cad52d6736..7c5e30c4e127206b8b6a5159a27dfb5b885dfeae 100644 (file)
@@ -21,6 +21,7 @@ import dns.edns
 import dns.flags
 import dns.message
 import dns.rcode
+import dns.rrset
 import dns.zone
 
 import isctest.log
index 60d42dcea7b7e0fd7c58e7fdc4fcb466a5346ca0..e5355eb3e0d6fba623d170fdb494089bf77a8111 100644 (file)
@@ -26,7 +26,6 @@ from hypothesis.strategies import (
     sampled_from,
 )
 
-import dns.message
 import dns.name
 import dns.rdataclass
 import dns.rdatatype
index cb542d79951fb91e2f81ab6e1b437ce949e75f64..2786f66e5d90555ddd46684f997724c675f99b61 100644 (file)
@@ -17,6 +17,7 @@ from typing import NamedTuple
 import os
 import re
 
+import dns.exception
 import dns.rcode
 import dns.update
 
index 29db2a55bfa306af32c7a3e140264bd2bd858fc0..1d4e8e6752041fb1599d0db2c5120ab56030f502 100644 (file)
@@ -20,11 +20,17 @@ import os
 import re
 import time
 
-import dns
 import dns.dnssec
+import dns.exception
+import dns.message
+import dns.name
+import dns.rcode
+import dns.rdataclass
 import dns.rdatatype
 import dns.rrset
 import dns.tsig
+import dns.zone
+import dns.zonefile
 
 from isctest.instance import NamedInstance
 from isctest.run import EnvCmd
index 9fc29e0008f5e1fe9cddd65a872b734837712048..7c767be167d60317633fd6f35a5e6ee57c74c0b2 100644 (file)
@@ -14,8 +14,12 @@ from typing import Any, Callable
 import os
 import time
 
+import dns.exception
+import dns.flags
 import dns.message
 import dns.query
+import dns.rcode
+import dns.rdataclass
 
 import isctest.log
 
index eec03ae72435af29a27bf33a5ea8a69b2dcb69a1..7ffce13b8ed8ddc0f3553162f99021bcfcfce132 100644 (file)
@@ -9,6 +9,7 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
+import dns.rrset
 import dns.zone
 import pytest
 
index cc041dff86ca39be0cefbe0dd13083c9a98887da..0c4f42ffda7b296b5797caaa88d2a2e50eb56ebc 100644 (file)
@@ -16,7 +16,12 @@ import shutil
 import subprocess
 import time
 
-import dns
+import dns.exception
+import dns.name
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
+import dns.tsig
 import dns.update
 import pytest
 
index 512c02ecca1a565361970ec0e7c79285c77cc328..c7498a22ecdff40d53d407999612cdf286191c7b 100644 (file)
@@ -11,6 +11,7 @@
 
 import itertools
 
+import dns.flags
 import dns.rrset
 import pytest
 
index 26f1e34ade42885589a85c156f540ddfe41e7a09..3e4150ee7f684f08cee05fe0787a598581bfcc76 100644 (file)
@@ -18,7 +18,6 @@ import pytest
 from isctest.vars.algorithms import Algorithm
 
 import isctest
-import isctest.mark
 
 pytestmark = pytest.mark.extra_artifacts(
     [
index 1ea3ddd6d81bfe42ed1e54168cfbe50bcd201257..d3db8ad163072763aa968dc14ca5a045cc1ea396 100644 (file)
@@ -14,7 +14,10 @@ from re import compile as Re
 
 import os
 
-import dns
+import dns.name
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
 import dns.update
 import pytest
 
index a53484ee3329e4b50d858a402af1124bed3f7759..bed0aadc280ed3362019f61c34f1a4baeba5e74b 100755 (executable)
@@ -26,7 +26,6 @@ from hypothesis import assume, given
 import dns.dnssec
 import dns.message
 import dns.name
-import dns.query
 import dns.rcode
 import dns.rdataclass
 import dns.rdatatype
index 542af0e622e94384c37901c1349c6f02a534c4fe..2f03f9bb35fc9d2ba84b215f248276bfb6bcad91 100644 (file)
@@ -11,7 +11,9 @@
 
 from datetime import timedelta
 
-import dns
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
 import pytest
 
 import isctest
index 9b9104cb7f190df643b11d246e0db2b93743d884..b8a8b066e36988a4c40eb39e6a22f22e7659fe21 100644 (file)
 import shutil
 import time
 
-import dns
-import dns.update
+import dns.name
+import dns.rdataclass
+import dns.rdatatype
 import pytest
 
 from isctest.vars.algorithms import Algorithm
 from nsec3.common import NSEC3_MARK, check_nsec3_case
 
 import isctest
-import isctest.mark
 
 pytestmark = NSEC3_MARK
 
index 465f11a76eb28cf4e14504f393186feab827a540..0cc53c81aa42fce0f40f55bd808db36e0c6df1d6 100644 (file)
@@ -11,7 +11,7 @@
 
 import os
 
-import dns
+import dns.rcode
 import dns.update
 import pytest
 
index 2a0bfecb27468791803e097d1e5a42c6e9ab6511..9efc486791daf3c1bfa43e3c3262d17488d6f2fc 100644 (file)
 import os
 import time
 
-import dns
-import dns.update
+import dns.name
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
 import pytest
 
 from isctest.vars.algorithms import RSASHA1, Algorithm
index b553ad120eb75843f7d3e28a57e1ccaa6dc8b787..ca6ebef8118e5fca8ddf6a05a139c130f104126c 100644 (file)
 
 import os
 
-import dns
-import dns.update
+import dns.rdatatype
 import pytest
 
 from isctest.vars.algorithms import Algorithm
 from nsec3.common import NSEC3_MARK, check_nsec3_case, check_nsec3param
 
 import isctest
-import isctest.mark
 
 pytestmark = NSEC3_MARK
 
index ff0208593daf5833679303e694d3bec75a205cd7..4df768cc00feefb594436a69ed6f0d36ae04be41 100644 (file)
@@ -13,14 +13,13 @@ from datetime import timedelta
 
 import os
 
-import dns
-import dns.update
+import dns.rcode
+import dns.rdatatype
 
 from isctest.vars.algorithms import RSASHA256
 from nsec3.common import NSEC3_MARK, check_auth_nsec3, check_nsec3param
 
 import isctest
-import isctest.mark
 
 pytestmark = NSEC3_MARK
 
index 3944649f2d8ddde9583645f19f629b4d77d8dd1e..ef157b3e9e4518e448c57c26c464284c0d7656c3 100755 (executable)
@@ -16,14 +16,9 @@ import os
 import re
 import sys
 
-import dns
-import dns.exception
-import dns.message
-import dns.name
 import dns.query
 import dns.rcode
-import dns.rdataclass
-import dns.rdatatype
+import dns.zone
 import pytest
 
 import isctest
index 20172a87b6c829ed2673d55d9443f63ab9bce57d..5d35903da83ae4337b446916e1b40f6b91f75198 100644 (file)
@@ -13,7 +13,6 @@ information regarding copyright ownership.
 
 from typing import AsyncGenerator
 
-import dns.message
 import dns.name
 import dns.rcode
 import dns.rdatatype
index c0c06f4b61fc5f897a6569929b3238c217021179..235ef99b6db68a0e2a2d54a35381b09007270045 100644 (file)
@@ -13,7 +13,6 @@ from datetime import timedelta
 
 import os
 
-import dns
 import dns.update
 
 from isctest.kasp import Iret, SettimeOptions
index 5eedc45e274a46193fa34eae7eec9a2ab9fb8372..904c6f03ac52ace919a44672a64ed066f1a35fd4 100644 (file)
@@ -13,7 +13,6 @@
 
 import os
 
-import dns
 import dns.rcode
 import dns.rrset
 import pytest
index 671ca877518b596bf89f9341797c70ce43638a25..61141344281e03dfa58c20721bb9906633856ad5 100755 (executable)
@@ -21,11 +21,9 @@ import itertools
 
 from dns.name import Name
 
-import dns
 import dns.name
 import pytest
 
-import isctest
 import isctest.name
 
 # set of properies present in the tested zone - read by tests_zone_analyzer.py
index b8bab680b62ceae12c0b16dd899515f5623eda13..77c705535e16a3efab23827338bd83f46a815db0 100644 (file)
@@ -9,7 +9,7 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
-import dns
+import dns.rcode
 
 import isctest
 
index 831f85c449f7a9ab4130baef78e2155d1f5b1f6c..aaa7cbad774e63588f986392b23cd57b59cf1f14 100755 (executable)
@@ -20,7 +20,6 @@ import signal
 import subprocess
 import time
 
-import dns
 import dns.exception
 import pytest
 
index 3e317087ebd1059c2c3dcf61291401c2458ea61f..0b0ee82de05da70952c167929021f8e6a3d81cf1 100644 (file)
@@ -16,8 +16,6 @@ from time import sleep
 import os
 
 import dns.message
-import dns.query
-import dns.rcode
 
 import isctest
 
index ef98b411374d28200abc11902faea01da5363b97..5864335c46be4ffbc08fa563cd7a7da929d4bf89 100644 (file)
@@ -12,6 +12,8 @@
 import concurrent.futures
 import time
 
+import dns.exception
+import dns.rcode
 import dns.update
 import pytest
 
index 2c9bd00cd60567fa9b2592bf10c5a0e0ea163c6a..8cf87c7ad83f18d1198165ffee44563f2f85b890 100644 (file)
@@ -12,7 +12,7 @@
 
 import os
 
-import dns.message
+import dns.rrset
 import pytest
 
 import isctest
index 7fbd5d7f0ccf9680a8b0e8a6d12a6b7dff82acc2..3579b7a33d98e1b35d88fd8ccb7b9b0e9dec6143 100644 (file)
@@ -24,7 +24,9 @@ from hypothesis import assume, example, given
 from hypothesis.strategies import ip_addresses
 
 import dns.message
-import dns.reversename
+import dns.name
+import dns.rcode
+import dns.rrset
 import pytest
 
 from isctest.hypothesis.strategies import dns_names
index 62d2f45a8c8782dc0e30af866abb833873e8c044..46c391c245569c18bc507232789e6b725d7eb255 100644 (file)
@@ -15,9 +15,11 @@ import socket
 import struct
 import time
 
-import dns
+import dns.flags
 import dns.message
+import dns.name
 import dns.query
+import dns.rrset
 import pytest
 
 pytestmark = pytest.mark.extra_artifacts(
index 478c0a345883108ef92284dcff66279fb89c7682..0d0660bd819d30ec763506c5b6194e1b01dc9d50 100644 (file)
@@ -14,7 +14,6 @@
 import socket
 import time
 
-import dns
 import dns.edns
 import dns.message
 import dns.name
index 9981463346ed9049e9b03e49cfa2dd60a8bc2b0d..7da1ef7357e1a6f2ee8bfe82d375defc562a9607 100644 (file)
@@ -16,6 +16,7 @@ import time
 
 import dns.message
 import dns.query
+import dns.tsig
 import dns.tsigkeyring
 import pytest
 
index 01e86e0fa9b4d56b0831904aa2077a4816d9224c..3193ea6c3fec9548087fc4570aa0acf988266aaf 100755 (executable)
@@ -20,8 +20,6 @@ import argparse
 import struct
 import time
 
-import dns
-import dns.message
 import dns.name
 import dns.rdata
 import dns.rdataclass
index dfe0dc831488504c97dcf5da8db1ef46c5f02621..3ea3fdc7d3e47942c77824900275994804ac50b0 100755 (executable)
@@ -33,11 +33,7 @@ Limitations - untested properties:
 
 from hypothesis import assume, example, given, settings
 
-import dns
-import dns.message
 import dns.name
-import dns.query
-import dns.rcode
 import dns.rdataclass
 import dns.rdatatype
 import dns.rrset
index d3c16cc24d41151e16a9ed242bedc5c36ce245d0..8aabb3a46a33dd0e0800ea2babc88013e1061104 100644 (file)
@@ -18,6 +18,11 @@ import socket
 import time
 
 import dns.message
+import dns.query
+import dns.rdataclass
+import dns.rdatatype
+import dns.tsig
+import dns.zone
 import pytest
 
 from isctest.util import param
index ba599471d5d4150db7639b84a0d621bd87280267..6d255085cb558638bab65579a746d4e837f3d2bb 100644 (file)
@@ -18,7 +18,7 @@ import shutil
 import signal
 import time
 
-import dns.message
+import dns.zone
 import pytest
 
 import isctest
index 88652777d5012b80b5e1acc957a54289839f449a..916b886cdaff1a6456bc8386e958523db77dd2f2 100644 (file)
@@ -58,6 +58,7 @@ source-roots = [
 ]
 load-plugins = [
   "re_compile_checker",
+  "dns_import_checker",
 ]
 
 [tool.vulture]
@@ -72,6 +73,7 @@ exclude = [
   "doc/man/conf.py",
   "isctest",
   "re_compile_checker.py",
+  "dns_import_checker.py",
 ]
 ignore_decorators = [
   "@pytest.fixture",