diff options
Diffstat (limited to 'pylint/checkers/utils.py')
-rw-r--r-- | pylint/checkers/utils.py | 51 |
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 |