summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--doc/whatsnew/2.12.rst4
-rw-r--r--pylint/checkers/variables.py20
-rw-r--r--tests/functional/u/unused/unused_name_from_wilcard_import.py4
-rw-r--r--tests/functional/u/unused/unused_name_from_wilcard_import.txt9
5 files changed, 34 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 99c3c2a67..b93132399 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,9 @@ Release date: TBA
..
Put new features here and also in 'doc/whatsnew/2.12.rst'
+* Improve and flatten ``unused-wildcard-import`` message
+
+ Closes #3859
What's New in Pylint 2.11.2?
diff --git a/doc/whatsnew/2.12.rst b/doc/whatsnew/2.12.rst
index 6a611eeb3..9bb00708e 100644
--- a/doc/whatsnew/2.12.rst
+++ b/doc/whatsnew/2.12.rst
@@ -23,3 +23,7 @@ Extensions
Other Changes
=============
+
+* Improve and flatten ``unused-wildcard-import`` message
+
+ Closes #3859
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index d77cba6fd..b2e38e113 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -60,6 +60,7 @@ import itertools
import os
import re
from functools import lru_cache
+from typing import DefaultDict, List, Tuple
import astroid
from astroid import nodes
@@ -449,7 +450,7 @@ MSGS = {
"Used when a function or method argument is not used.",
),
"W0614": (
- "Unused import %s from wildcard import",
+ "Unused import(s) %s from wildcard import of %s",
"unused-wildcard-import",
"Used when an imported module or variable is not used from a "
"`'from X import *'` style import.",
@@ -2079,6 +2080,9 @@ class VariablesChecker(BaseChecker):
def _check_imports(self, not_consumed):
local_names = _fix_dot_imports(not_consumed)
checked = set()
+ unused_wildcard_imports: DefaultDict[
+ Tuple[str, nodes.ImportFrom], List[str]
+ ] = collections.defaultdict(list)
for name, stmt in local_names:
for imports in stmt.names:
real_name = imported_name = imports[0]
@@ -2133,7 +2137,7 @@ class VariablesChecker(BaseChecker):
continue
if imported_name == "*":
- self.add_message("unused-wildcard-import", args=name, node=stmt)
+ unused_wildcard_imports[(stmt.modname, stmt)].append(name)
else:
if as_name is None:
msg = f"{imported_name} imported from {stmt.modname}"
@@ -2141,6 +2145,18 @@ class VariablesChecker(BaseChecker):
msg = f"{imported_name} imported from {stmt.modname} as {as_name}"
if not _is_type_checking_import(stmt):
self.add_message("unused-import", args=msg, node=stmt)
+
+ # Construct string for unused-wildcard-import message
+ for module, unused_list in unused_wildcard_imports.items():
+ if len(unused_list) == 1:
+ arg_string = unused_list[0]
+ else:
+ arg_string = (
+ f"{', '.join(i for i in unused_list[:-1])} and {unused_list[-1]}"
+ )
+ self.add_message(
+ "unused-wildcard-import", args=(arg_string, module[0]), node=module[1]
+ )
del self._to_consume
def _check_metaclasses(self, node):
diff --git a/tests/functional/u/unused/unused_name_from_wilcard_import.py b/tests/functional/u/unused/unused_name_from_wilcard_import.py
index 292d40f95..54658b855 100644
--- a/tests/functional/u/unused/unused_name_from_wilcard_import.py
+++ b/tests/functional/u/unused/unused_name_from_wilcard_import.py
@@ -1,3 +1,5 @@
"""check unused import from a wildcard import"""
# pylint: disable=line-too-long
-from .unused_argument_py3 import * # [unused-wildcard-import, unused-wildcard-import, wildcard-import]
+from .unused_argument_py3 import * # [unused-wildcard-import, wildcard-import]
+from .unused_global_variable1 import * # [unused-wildcard-import, wildcard-import]
+from .unused_import_py30 import * # [unused-wildcard-import, wildcard-import]
diff --git a/tests/functional/u/unused/unused_name_from_wilcard_import.txt b/tests/functional/u/unused/unused_name_from_wilcard_import.txt
index ba7628ba8..525afd2fc 100644
--- a/tests/functional/u/unused/unused_name_from_wilcard_import.txt
+++ b/tests/functional/u/unused/unused_name_from_wilcard_import.txt
@@ -1,3 +1,6 @@
-unused-wildcard-import:3:0::Unused import func from wildcard import
-unused-wildcard-import:3:0::Unused import only_raises from wildcard import
-wildcard-import:3:0::Wildcard import unused_argument_py3
+unused-wildcard-import:3:0::Unused import(s) func and only_raises from wildcard import of unused_argument_py3:HIGH
+wildcard-import:3:0::Wildcard import unused_argument_py3:HIGH
+unused-wildcard-import:4:0::Unused import(s) VAR from wildcard import of unused_global_variable1:HIGH
+wildcard-import:4:0::Wildcard import unused_global_variable1:HIGH
+unused-wildcard-import:5:0::Unused import(s) abc, sys, Meta, Meta2, Meta3, ABCMeta and SomethingElse from wildcard import of unused_import_py30:HIGH
+wildcard-import:5:0::Wildcard import unused_import_py30:HIGH