summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatus Valo <matusvalo@users.noreply.github.com>2021-03-17 23:03:18 +0100
committerGitHub <noreply@github.com>2021-03-17 23:03:18 +0100
commitcdfc8374b1b0ee88af0463bdbe58299186244d53 (patch)
tree113c71198672978be5efb41e892f34412ba8810e
parentf94b6d5ce5f22299d253d97eda1bf9e10045ce89 (diff)
downloadpylint-git-cdfc8374b1b0ee88af0463bdbe58299186244d53.tar.gz
Move deprecated module checker to DeprecatedMixin (#4225)
* Move deprecated module checker to DeprecatedMixin Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r--ChangeLog4
-rw-r--r--pylint/checkers/deprecated.py33
-rw-r--r--pylint/checkers/imports.py22
-rw-r--r--tests/checkers/unittest_deprecated.py37
4 files changed, 84 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index ac5a90330..ea04a5ab9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,10 @@ Release date: TBA
alternative to ``extension-pkg-whitelist`` and the message ``blacklisted-name`` is now emitted as
``disallowed-name``. The previous names are accepted to maintain backward compatibility.
+* Move deprecated checker to ``DeprecatedMixin``
+
+ Closes #4086
+
What's New in Pylint 2.7.3?
===========================
diff --git a/pylint/checkers/deprecated.py b/pylint/checkers/deprecated.py
index 9a4f636e4..8aaa02506 100644
--- a/pylint/checkers/deprecated.py
+++ b/pylint/checkers/deprecated.py
@@ -32,6 +32,11 @@ class DeprecatedMixin:
"deprecated-argument",
"The argument is marked as deprecated and will be removed in the future.",
),
+ "W0402": (
+ "Uses of a deprecated module %r",
+ "deprecated-module",
+ "A module marked as deprecated is imported.",
+ ),
}
@utils.check_messages(
@@ -47,6 +52,18 @@ class DeprecatedMixin:
except astroid.InferenceError:
pass
+ @utils.check_messages("deprecated-module")
+ def visit_import(self, node):
+ """triggered when an import statement is seen"""
+ for name in (name for name, _ in node.names):
+ self.check_deprecated_module(node, name)
+
+ @utils.check_messages("deprecated-module")
+ def visit_importfrom(self, node):
+ """triggered when a from statement is seen"""
+ basename = node.modname
+ self.check_deprecated_module(node, basename)
+
def deprecated_methods(self) -> Container[str]:
"""Callback returning the deprecated methods/functions.
@@ -85,6 +102,22 @@ class DeprecatedMixin:
# pylint: disable=unused-argument
return ()
+ def deprecated_modules(self) -> Iterable:
+ """Callback returning the deprecated modules.
+
+ Returns:
+ collections.abc.Container of deprecated module names.
+ """
+ # pylint: disable=no-self-use
+ return ()
+
+ def check_deprecated_module(self, node, mod_path):
+ """Checks if the module is deprecated"""
+
+ for mod_name in self.deprecated_modules():
+ if mod_path == mod_name or mod_path.startswith(mod_name + "."):
+ self.add_message("deprecated-module", node=node, args=mod_path)
+
def check_deprecated_method(self, node, inferred):
"""Executes the checker for the given node. This method should
be called from the checker implementing this mixin.
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index 82ff07448..ba14108c4 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -49,7 +49,7 @@ import astroid
from astroid import modutils
from astroid.decorators import cached
-from pylint.checkers import BaseChecker
+from pylint.checkers import BaseChecker, DeprecatedMixin
from pylint.checkers.utils import (
check_messages,
is_from_fallback_block,
@@ -292,7 +292,7 @@ DEFAULT_KNOWN_THIRD_PARTY = ("enchant",)
DEFAULT_PREFERRED_MODULES = ()
-class ImportsChecker(BaseChecker):
+class ImportsChecker(DeprecatedMixin, BaseChecker):
"""checks for
* external modules dependencies
* relative / wildcard imports
@@ -306,13 +306,13 @@ class ImportsChecker(BaseChecker):
name = "imports"
msgs = MSGS
priority = -2
- deprecated_modules = ("optparse", "tkinter.tix")
+ default_deprecated_modules = ("optparse", "tkinter.tix")
options = (
(
"deprecated-modules",
{
- "default": deprecated_modules,
+ "default": default_deprecated_modules,
"type": "csv",
"metavar": "<modules>",
"help": "Deprecated modules which should not be used,"
@@ -487,6 +487,10 @@ class ImportsChecker(BaseChecker):
for cycle in get_cycles(graph, vertices=vertices):
self.add_message("cyclic-import", args=" -> ".join(cycle))
+ def deprecated_modules(self):
+ """Callback returning the deprecated modules."""
+ return self.config.deprecated_modules
+
@check_messages(*MSGS)
def visit_import(self, node):
"""triggered when an import statement is seen"""
@@ -499,7 +503,7 @@ class ImportsChecker(BaseChecker):
self.add_message("multiple-imports", args=", ".join(names), node=node)
for name in names:
- self._check_deprecated_module(node, name)
+ self.check_deprecated_module(node, name)
self._check_preferred_module(node, name)
imported_module = self._get_imported_module(node, name)
if isinstance(node.parent, astroid.Module):
@@ -521,7 +525,7 @@ class ImportsChecker(BaseChecker):
self._check_import_as_rename(node)
self._check_misplaced_future(node)
- self._check_deprecated_module(node, basename)
+ self.check_deprecated_module(node, basename)
self._check_preferred_module(node, basename)
self._check_wildcard_imports(node, imported_module)
self._check_same_line_imports(node)
@@ -832,12 +836,6 @@ class ImportsChecker(BaseChecker):
if not self.linter.is_message_enabled("cyclic-import", line=node.lineno):
self._excluded_edges[context_name].add(importedmodname)
- def _check_deprecated_module(self, node, mod_path):
- """check if the module is deprecated"""
- for mod_name in self.config.deprecated_modules:
- if mod_path == mod_name or mod_path.startswith(mod_name + "."):
- self.add_message("deprecated-module", node=node, args=mod_path)
-
def _check_preferred_module(self, node, mod_path):
"""check if the module has a preferred replacement"""
if mod_path in self.preferred_modules:
diff --git a/tests/checkers/unittest_deprecated.py b/tests/checkers/unittest_deprecated.py
index f7e8c1309..f9b45cd6d 100644
--- a/tests/checkers/unittest_deprecated.py
+++ b/tests/checkers/unittest_deprecated.py
@@ -12,6 +12,9 @@ class _DeprecatedChecker(DeprecatedMixin, BaseChecker):
def deprecated_methods(self):
return {"deprecated_func", ".Deprecated.deprecated_method"}
+ def deprecated_modules(self):
+ return {"deprecated_module"}
+
def deprecated_arguments(self, method):
if method == "myfunction1":
# def myfunction1(arg1, deprecated_arg1='spam')
@@ -355,3 +358,37 @@ class TestDeprecatedChecker(CheckerTestCase):
),
):
self.checker.visit_call(node)
+
+ def test_deprecated_module(self):
+ # Tests detecting deprecated module
+ node = astroid.extract_node(
+ """
+ import deprecated_module
+ """
+ )
+ with self.assertAddsMessages(
+ Message(
+ msg_id="deprecated-module",
+ args="deprecated_module",
+ node=node,
+ confidence=UNDEFINED,
+ )
+ ):
+ self.checker.visit_import(node)
+
+ def test_deprecated_module_from(self):
+ # Tests detecting deprecated module
+ node = astroid.extract_node(
+ """
+ from deprecated_module import myfunction
+ """
+ )
+ with self.assertAddsMessages(
+ Message(
+ msg_id="deprecated-module",
+ args="deprecated_module",
+ node=node,
+ confidence=UNDEFINED,
+ )
+ ):
+ self.checker.visit_importfrom(node)