diff options
Diffstat (limited to 'pylint/lint/pylinter.py')
-rw-r--r-- | pylint/lint/pylinter.py | 167 |
1 files changed, 40 insertions, 127 deletions
diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py index 863076f8f..ed607aca5 100644 --- a/pylint/lint/pylinter.py +++ b/pylint/lint/pylinter.py @@ -1,6 +1,6 @@ # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE -# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt +# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE +# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt from __future__ import annotations @@ -12,14 +12,13 @@ import os import sys import tokenize import traceback -import warnings from collections import defaultdict from collections.abc import Callable, Iterator, Sequence from io import TextIOWrapper from pathlib import Path from re import Pattern from types import ModuleType -from typing import Any +from typing import Any, Protocol import astroid from astroid import nodes @@ -69,12 +68,6 @@ from pylint.typing import ( ) from pylint.utils import ASTWalker, FileState, LinterStats, utils -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from typing_extensions import Protocol - - MANAGER = astroid.MANAGER @@ -139,26 +132,38 @@ MSGS: dict[str, MessageDefinitionTuple] = { "raw-checker-failed", "Used to inform that a built-in module has not been checked " "using the raw checkers.", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0010": ( "Unable to consider inline option %r", "bad-inline-option", "Used when an inline option is either badly formatted or can't " "be used inside modules.", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0011": ( "Locally disabling %s (%s)", "locally-disabled", "Used when an inline option disables a message or a messages category.", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0013": ( "Ignoring entire file", "file-ignored", "Used to inform that the file will not be checked", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0020": ( "Suppressed %s (from line %d)", @@ -167,14 +172,20 @@ MSGS: dict[str, MessageDefinitionTuple] = { "by a disable= comment in the file. This message is not " "generated for messages that are ignored due to configuration " "settings.", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0021": ( "Useless suppression of %s", "useless-suppression", "Reported when a message is explicitly disabled for a line or " "a block of code, but never triggered.", - {"scope": WarningScope.LINE}, + { + "scope": WarningScope.LINE, + "default_enabled": False, + }, ), "I0022": ( 'Pragma "%s" is deprecated, use "%s" instead', @@ -185,6 +196,7 @@ MSGS: dict[str, MessageDefinitionTuple] = { { "old_names": [("I0014", "deprecated-disable-all")], "scope": WarningScope.LINE, + "default_enabled": False, }, ), "E0001": ( @@ -311,7 +323,8 @@ class PyLinter( self.options: Options = options + _make_linter_options(self) for opt_group in option_groups: self.option_groups_descs[opt_group[0]] = opt_group[1] - self._option_groups: tuple[tuple[str, str], ...] = option_groups + ( + self._option_groups: tuple[tuple[str, str], ...] = ( + *option_groups, ("Messages control", "Options controlling analysis messages"), ("Reports", "Options related to output formatting and reporting"), ) @@ -339,32 +352,13 @@ class PyLinter( # Attributes related to visiting files self.file_state = FileState("", self.msgs_store, is_base_filestate=True) - self.current_name: str | None = None + self.current_name: str = "" self.current_file: str | None = None self._ignore_file = False self._ignore_paths: list[Pattern[str]] = [] self.register_checker(self) - @property - def option_groups(self) -> tuple[tuple[str, str], ...]: - # TODO: 3.0: Remove deprecated attribute - warnings.warn( - "The option_groups attribute has been deprecated and will be removed in pylint 3.0", - DeprecationWarning, - stacklevel=2, - ) - return self._option_groups - - @option_groups.setter - def option_groups(self, value: tuple[tuple[str, str], ...]) -> None: - warnings.warn( - "The option_groups attribute has been deprecated and will be removed in pylint 3.0", - DeprecationWarning, - stacklevel=2, - ) - self._option_groups = value - def load_default_plugins(self) -> None: checkers.initialize(self) reporters.initialize(self) @@ -655,23 +649,12 @@ class PyLinter( else: yield something - def check(self, files_or_modules: Sequence[str] | str) -> None: + def check(self, files_or_modules: Sequence[str]) -> None: """Main checking entry: check a list of files or modules from their name. files_or_modules is either a string or list of strings presenting modules to check. """ - # 1) Initialize self.initialize() - - # 2) Gather all files - if not isinstance(files_or_modules, (list, tuple)): - # TODO: 3.0: Remove deprecated typing and update docstring - warnings.warn( - "In pylint 3.0, the checkers check function will only accept sequence of string", - DeprecationWarning, - stacklevel=2, - ) - files_or_modules = (files_or_modules,) # type: ignore[assignment] if self.config.recursive: files_or_modules = tuple(self._discover_files(files_or_modules)) if self.config.from_stdin: @@ -687,7 +670,7 @@ class PyLinter( } ) - # TODO: Move the parallel invocation into step 5 of the checking process + # TODO: Move the parallel invocation into step 3 of the checking process if not self.config.from_stdin and self.config.jobs > 1: original_sys_path = sys.path[:] check_parallel( @@ -699,7 +682,7 @@ class PyLinter( sys.path = original_sys_path return - # 3) Get all FileItems + # 1) Get all FileItems with augmented_sys_path(extra_packages_paths): if self.config.from_stdin: fileitems = self._get_file_descr_from_stdin(files_or_modules[0]) @@ -711,10 +694,10 @@ class PyLinter( # The contextmanager also opens all checkers and sets up the PyLinter class with augmented_sys_path(extra_packages_paths): with self._astroid_module_checker() as check_astroid_module: - # 4) Get the AST for each FileItem + # 2) Get the AST for each FileItem ast_per_fileitem = self._get_asts(fileitems, data) - # 5) Lint each ast + # 3) Lint each ast self._lint_files(ast_per_fileitem, check_astroid_module) def _get_asts( @@ -743,15 +726,6 @@ class PyLinter( return ast_per_fileitem - def check_single_file(self, name: str, filepath: str, modname: str) -> None: - warnings.warn( - "In pylint 3.0, the checkers check_single_file function will be removed. " - "Use check_single_file_item instead.", - DeprecationWarning, - stacklevel=2, - ) - self.check_single_file_item(FileItem(name, filepath, modname)) - def check_single_file_item(self, file: FileItem) -> None: """Check single file item. @@ -919,26 +893,13 @@ class PyLinter( self.add_message(key, args=message) return result - def set_current_module( - self, modname: str | None, filepath: str | None = None - ) -> None: + def set_current_module(self, modname: str, filepath: str | None = None) -> None: """Set the name of the currently analyzed module and init statistics for it. """ if not modname and filepath is None: return self.reporter.on_set_current_module(modname or "", filepath) - if modname is None: - # TODO: 3.0: Remove all modname or ""'s in this method - warnings.warn( - ( - "In pylint 3.0 modname should be a string so that it can be used to " - "correctly set the current_name attribute of the linter instance. " - "If unknown it should be initialized as an empty string." - ), - DeprecationWarning, - stacklevel=2, - ) self.current_name = modname self.current_file = filepath or modname self.stats.init_single_module(modname or "") @@ -976,41 +937,9 @@ class PyLinter( tokencheckers = [ c for c in _checkers if isinstance(c, checkers.BaseTokenChecker) ] - # TODO: 3.0: Remove deprecated for-loop - for c in _checkers: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=DeprecationWarning) - if ( - interfaces.implements(c, interfaces.ITokenChecker) - and c not in tokencheckers - and c is not self - ): - tokencheckers.append(c) # type: ignore[arg-type] # pragma: no cover - warnings.warn( # pragma: no cover - "Checkers should subclass BaseTokenChecker " - "instead of using the __implements__ mechanism. Use of __implements__ " - "will no longer be supported in pylint 3.0", - DeprecationWarning, - ) rawcheckers = [ c for c in _checkers if isinstance(c, checkers.BaseRawFileChecker) ] - # TODO: 3.0: Remove deprecated if-statement - for c in _checkers: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=DeprecationWarning) - if ( - interfaces.implements(c, interfaces.IRawChecker) - and c not in rawcheckers - ): - rawcheckers.append(c) # type: ignore[arg-type] # pragma: no cover - warnings.warn( # pragma: no cover - "Checkers should subclass BaseRawFileChecker " - "instead of using the __implements__ mechanism. Use of __implements__ " - "will no longer be supported in pylint 3.0", - DeprecationWarning, - ) - # notify global begin for checker in _checkers: checker.open() walker.add_checker(checker) @@ -1085,10 +1014,6 @@ class PyLinter( retval = self._check_astroid_module( ast_node, walker, rawcheckers, tokencheckers ) - - # TODO: 3.0: Remove unnecessary assertion - assert self.current_name - self.stats.by_module[self.current_name]["statement"] = ( walker.nbstatements - before_check_statements ) @@ -1154,12 +1079,7 @@ class PyLinter( """ # Display whatever messages are left on the reporter. self.reporter.display_messages(report_nodes.Section()) - - # TODO: 3.0: Remove second half of if-statement - if ( - not self.file_state._is_base_filestate - and self.file_state.base_name is not None - ): + if not self.file_state._is_base_filestate: # load previous results if any previous_stats = load_results(self.file_state.base_name) self.reporter.on_close(self.stats, previous_stats) @@ -1181,11 +1101,9 @@ class PyLinter( def _report_evaluation(self) -> int | None: """Make the global evaluation report.""" - # check with at least check 1 statements (usually 0 when there is a + # check with at least a statement (usually 0 when there is a # syntax error preventing pylint from further processing) note = None - # TODO: 3.0: Remove assertion - assert self.file_state.base_name is not None previous_stats = load_results(self.file_state.base_name) if self.stats.statement == 0: return note @@ -1270,12 +1188,7 @@ class PyLinter( msg_cat = MSG_TYPES[message_definition.msgid[0]] self.msg_status |= MSG_TYPES_STATUS[message_definition.msgid[0]] self.stats.increase_single_message_count(msg_cat, 1) - # TODO: 3.0 Should be removable after https://github.com/PyCQA/pylint/pull/5580 - self.stats.increase_single_module_message_count( - self.current_name, # type: ignore[arg-type] - msg_cat, - 1, - ) + self.stats.increase_single_module_message_count(self.current_name, msg_cat, 1) try: self.stats.by_msg[message_definition.symbol] += 1 except KeyError: |