summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
authorDaniel Mouritzen <dmrtzn@gmail.com>2023-04-04 05:44:15 +0900
committerGitHub <noreply@github.com>2023-04-03 22:44:15 +0200
commit9fa662ca9c1b20bd2781e564d6a78d31111e5bb0 (patch)
treecdc16d5c2dda6736e2727f8a1aa500a38d07dbf2 /pylint
parent2e6468f7f986032dad0e1ce5e5c8aa7f5d9e55fb (diff)
downloadpylint-git-9fa662ca9c1b20bd2781e564d6a78d31111e5bb0.tar.gz
Handle patterns in ignored-modules when checking for no-name-in-module (#7579)
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com> Co-authored-by: Jared Proffitt <jaredproffitt@gmail.com>
Diffstat (limited to 'pylint')
-rw-r--r--pylint/checkers/imports.py22
-rw-r--r--pylint/checkers/typecheck.py2
-rw-r--r--pylint/checkers/utils.py46
-rw-r--r--pylint/checkers/variables.py5
4 files changed, 29 insertions, 46 deletions
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index 9f4b0e379..6cc5d2164 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -23,6 +23,7 @@ from pylint.checkers.utils import (
get_import_name,
in_type_checking_block,
is_from_fallback_block,
+ is_module_ignored,
is_sys_guard,
node_ignores_exception,
)
@@ -84,18 +85,6 @@ DEPRECATED_MODULES = {
}
-def _qualified_names(modname: str | None) -> list[str]:
- """Split the names of the given module into subparts.
-
- For example,
- _qualified_names('pylint.checkers.ImportsChecker')
- returns
- ['pylint', 'pylint.checkers', 'pylint.checkers.ImportsChecker']
- """
- names = modname.split(".") if modname is not None else ""
- return [".".join(names[0 : i + 1]) for i in range(len(names))]
-
-
def _get_first_import(
node: ImportNode,
context: nodes.LocalsDictNodeNG,
@@ -153,12 +142,11 @@ def _get_first_import(
def _ignore_import_failure(
node: ImportNode,
- modname: str | None,
+ modname: str,
ignored_modules: Sequence[str],
) -> bool:
- for submodule in _qualified_names(modname):
- if submodule in ignored_modules:
- return True
+ if is_module_ignored(modname, ignored_modules):
+ return True
# Ignore import failure if part of guarded import block
# I.e. `sys.version_info` or `typing.TYPE_CHECKING`
@@ -852,7 +840,7 @@ class ImportsChecker(DeprecatedMixin, BaseChecker):
return std_imports, external_imports, local_imports
def _get_imported_module(
- self, importnode: ImportNode, modname: str | None
+ self, importnode: ImportNode, modname: str
) -> nodes.Module | None:
try:
return importnode.do_import_module(modname)
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index 90604261d..42131f936 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -124,7 +124,7 @@ def _is_owner_ignored(
matches any name from the *ignored_classes* or if its qualified
name can be found in *ignored_classes*.
"""
- if is_module_ignored(owner.root(), ignored_modules):
+ if is_module_ignored(owner.root().qname(), ignored_modules):
return True
# Match against ignored classes.
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index 4b316909e..38321bc11 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -12,7 +12,6 @@ import itertools
import numbers
import re
import string
-from collections import deque
from collections.abc import Iterable, Iterator
from functools import lru_cache, partial
from re import Match
@@ -2050,37 +2049,30 @@ def is_augmented_assign(node: nodes.Assign) -> tuple[bool, str]:
return False, ""
+def _qualified_name_parts(qualified_module_name: str) -> list[str]:
+ """Split the names of the given module into subparts.
+
+ For example,
+ _qualified_name_parts('pylint.checkers.ImportsChecker')
+ returns
+ ['pylint', 'pylint.checkers', 'pylint.checkers.ImportsChecker']
+ """
+ names = qualified_module_name.split(".")
+ return [".".join(names[0 : i + 1]) for i in range(len(names))]
+
+
def is_module_ignored(
- module: nodes.Module,
- ignored_modules: Iterable[str],
+ qualified_module_name: str, ignored_modules: Iterable[str]
) -> bool:
ignored_modules = set(ignored_modules)
- module_name = module.name
- module_qname = module.qname()
-
- for ignore in ignored_modules:
- # Try to match the module name / fully qualified name directly
- if module_qname in ignored_modules or module_name in ignored_modules:
+ for current_module in _qualified_name_parts(qualified_module_name):
+ # Try to match the module name directly
+ if current_module in ignored_modules:
return True
-
- # Try to see if the ignores pattern match against the module name.
- if fnmatch.fnmatch(module_qname, ignore):
- return True
-
- # Otherwise, we might have a root module name being ignored,
- # and the qualified owner has more levels of depth.
- parts = deque(module_name.split("."))
- current_module = ""
-
- while parts:
- part = parts.popleft()
- if not current_module:
- current_module = part
- else:
- current_module += f".{part}"
- if current_module in ignored_modules:
+ for ignore in ignored_modules:
+ # Try to see if the ignores pattern match against the module name.
+ if fnmatch.fnmatch(current_module, ignore):
return True
-
return False
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 0a24de370..79bdb6a97 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -25,6 +25,7 @@ from astroid.typing import InferenceResult
from pylint.checkers import BaseChecker, utils
from pylint.checkers.utils import (
in_type_checking_block,
+ is_module_ignored,
is_postponed_evaluation_enabled,
is_sys_guard,
overridden_method,
@@ -2941,7 +2942,9 @@ class VariablesChecker(BaseChecker):
if not isinstance(module, nodes.Module):
return None
except astroid.NotFoundError:
- if module.name in self._ignored_modules:
+ # Unable to import `name` from `module`. Since `name` may itself be a
+ # module, we first check if it matches the ignored modules.
+ if is_module_ignored(f"{module.qname()}.{name}", self._ignored_modules):
return None
self.add_message(
"no-name-in-module", args=(name, module.name), node=node