summaryrefslogtreecommitdiff
path: root/pylint/checkers/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'pylint/checkers/utils.py')
-rw-r--r--pylint/checkers/utils.py51
1 files changed, 50 insertions, 1 deletions
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index d00b8a653..b7e0596d1 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -7,11 +7,13 @@
from __future__ import annotations
import builtins
+import fnmatch
import itertools
import numbers
import re
import string
import warnings
+from collections import deque
from collections.abc import Iterable, Iterator
from functools import lru_cache, partial
from re import Match
@@ -1331,12 +1333,18 @@ def _get_python_type_of_node(node: nodes.NodeNG) -> str | None:
@lru_cache(maxsize=1024)
def safe_infer(
- node: nodes.NodeNG, context: InferenceContext | None = None
+ node: nodes.NodeNG,
+ context: InferenceContext | None = None,
+ *,
+ compare_constants: bool = False,
) -> InferenceResult | None:
"""Return the inferred value for the given node.
Return None if inference failed or if there is some ambiguity (more than
one node has been inferred of different types).
+
+ If compare_constants is True and if multiple constants are inferred,
+ unequal inferred values are also considered ambiguous and return None.
"""
inferred_types: set[str | None] = set()
try:
@@ -1356,6 +1364,13 @@ def safe_infer(
if inferred_type not in inferred_types:
return None # If there is ambiguity on the inferred node.
if (
+ compare_constants
+ and isinstance(inferred, nodes.Const)
+ and isinstance(value, nodes.Const)
+ and inferred.value != value.value
+ ):
+ return None
+ if (
isinstance(inferred, nodes.FunctionDef)
and inferred.args.args is not None
and isinstance(value, nodes.FunctionDef)
@@ -1952,3 +1967,37 @@ def is_hashable(node: nodes.NodeNG) -> bool:
return False
except astroid.InferenceError:
return True
+
+
+def is_module_ignored(
+ module: nodes.Module,
+ 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:
+ 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:
+ return True
+
+ return False