diff --git a/pylint/checkers/base/__init__.py b/pylint/checkers/base/__init__.py index 7c162441b0..38b43baddb 100644 --- a/pylint/checkers/base/__init__.py +++ b/pylint/checkers/base/__init__.py @@ -2,6 +2,7 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt +from __future__ import annotations __all__ = [ "NameChecker", @@ -36,7 +37,7 @@ from pylint.lint import PyLinter -def register(linter: "PyLinter") -> None: +def register(linter: PyLinter) -> None: linter.register_checker(BasicErrorChecker(linter)) linter.register_checker(BasicChecker(linter)) linter.register_checker(NameChecker(linter)) diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index 55ce39d900..ab77b3b485 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -4,10 +4,12 @@ """Basic checker for Python code.""" +from __future__ import annotations + import collections import itertools import sys -from typing import TYPE_CHECKING, Dict, Optional, cast +from typing import TYPE_CHECKING, cast import astroid from astroid import nodes @@ -64,7 +66,7 @@ class _BasicChecker(BaseChecker): def report_by_type_stats( sect, stats: LinterStats, - old_stats: Optional[LinterStats], + old_stats: LinterStats | None, ): """Make a report of. @@ -72,7 +74,7 @@ def report_by_type_stats( * percentage of different types with a bad name """ # percentage of different types documented and/or with a bad name - nice_stats: Dict[str, Dict[str, str]] = {} + nice_stats: dict[str, dict[str, str]] = {} for node_type in ("module", "class", "method", "function"): node_type = cast(Literal["function", "class", "method", "module"], node_type) total = stats.get_node_count(node_type) diff --git a/pylint/checkers/base/name_checker/checker.py b/pylint/checkers/base/name_checker/checker.py index af424f4220..f77cfc5b06 100644 --- a/pylint/checkers/base/name_checker/checker.py +++ b/pylint/checkers/base/name_checker/checker.py @@ -3,12 +3,15 @@ # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt """Basic checker for Python code.""" + +from __future__ import annotations + import collections import itertools import re import sys from enum import Enum, auto -from typing import Dict, Optional, Pattern, Tuple +from typing import Pattern import astroid from astroid import nodes @@ -283,9 +286,9 @@ def open(self): re.compile(rgxp) for rgxp in self.linter.namespace.bad_names_rgxs ] - def _create_naming_rules(self) -> Tuple[Dict[str, Pattern[str]], Dict[str, str]]: - regexps: Dict[str, Pattern[str]] = {} - hints: Dict[str, str] = {} + def _create_naming_rules(self) -> tuple[dict[str, Pattern[str]], dict[str, str]]: + regexps: dict[str, Pattern[str]] = {} + hints: dict[str, str] = {} for name_type in KNOWN_NAME_TYPES: if name_type in KNOWN_NAME_TYPES_WITH_STYLE: @@ -473,7 +476,7 @@ def _find_name_group(self, node_type): def _raise_name_warning( self, - prevalent_group: Optional[str], + prevalent_group: str | None, node: nodes.NodeNG, node_type: str, name: str, @@ -560,7 +563,7 @@ def _name_became_keyword_in_version(name, rules): return None @staticmethod - def _assigns_typevar(node: Optional[nodes.NodeNG]) -> bool: + def _assigns_typevar(node: nodes.NodeNG | None) -> bool: """Check if a node is assigning a TypeVar.""" if isinstance(node, astroid.Call): inferred = utils.safe_infer(node.func) diff --git a/pylint/checkers/classes/__init__.py b/pylint/checkers/classes/__init__.py index 5e9bc5ae36..e511944390 100644 --- a/pylint/checkers/classes/__init__.py +++ b/pylint/checkers/classes/__init__.py @@ -2,6 +2,8 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt +from __future__ import annotations + from typing import TYPE_CHECKING from pylint.checkers.classes.class_checker import ClassChecker @@ -11,6 +13,6 @@ from pylint.lint import PyLinter -def register(linter: "PyLinter") -> None: +def register(linter: PyLinter) -> None: linter.register_checker(ClassChecker(linter)) linter.register_checker(SpecialMethodsChecker(linter)) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 40d806d752..619a23330d 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -3,10 +3,13 @@ # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt """Classes checker for Python code.""" + +from __future__ import annotations + import collections import sys from itertools import chain, zip_longest -from typing import Dict, List, Pattern, Set +from typing import Pattern import astroid from astroid import bases, nodes @@ -187,11 +190,11 @@ def _has_different_parameters_default_value(original, overridden): def _has_different_parameters( - original: List[nodes.AssignName], - overridden: List[nodes.AssignName], + original: list[nodes.AssignName], + overridden: list[nodes.AssignName], dummy_parameter_regex: Pattern, -) -> List[str]: - result: List[str] = [] +) -> list[str]: + result: list[str] = [] zipped = zip_longest(original, overridden) for original_param, overridden_param in zipped: if not overridden_param: @@ -218,9 +221,9 @@ def _has_different_parameters( def _has_different_keyword_only_parameters( - original: List[nodes.AssignName], - overridden: List[nodes.AssignName], -) -> List[str]: + original: list[nodes.AssignName], + overridden: list[nodes.AssignName], +) -> list[str]: """Determine if the two methods have different keyword only parameters.""" original_names = [i.name for i in original] overridden_names = [i.name for i in overridden] @@ -244,7 +247,7 @@ def _different_parameters( original: nodes.FunctionDef, overridden: nodes.FunctionDef, dummy_parameter_regex: Pattern, -) -> List[str]: +) -> list[str]: """Determine if the two methods have different parameters. They are considered to have different parameters if: @@ -980,7 +983,7 @@ def _check_unused_private_attributes(self, node: nodes.ClassDef) -> None: # Logic for checking false positive when using __new__, # Get the returned object names of the __new__ magic function # Then check if the attribute was consumed in other instance methods - acceptable_obj_names: List[str] = ["self"] + acceptable_obj_names: list[str] = ["self"] scope = assign_attr.scope() if isinstance(scope, nodes.FunctionDef) and scope.name == "__new__": acceptable_obj_names.extend( @@ -1391,10 +1394,10 @@ def _check_redefined_slots( self, node: nodes.ClassDef, slots_node: nodes.NodeNG, - slots_list: List[nodes.NodeNG], + slots_list: list[nodes.NodeNG], ) -> None: """Check if `node` redefines a slot which is defined in an ancestor class.""" - slots_names: List[str] = [] + slots_names: list[str] = [] for slot in slots_list: if isinstance(slot, nodes.Const): slots_names.append(slot.value) @@ -1971,7 +1974,7 @@ def _check_init(self, node: nodes.FunctionDef, klass_node: nodes.ClassDef) -> No return to_call = _ancestors_to_call(klass_node) not_called_yet = dict(to_call) - parents_with_called_inits: Set[bases.UnboundMethod] = set() + parents_with_called_inits: set[bases.UnboundMethod] = set() for stmt in node.nodes_of_class(nodes.Call): expr = stmt.func if not isinstance(expr, nodes.Attribute) or expr.attrname != "__init__": @@ -2155,11 +2158,11 @@ def _is_mandatory_method_param(self, node: nodes.NodeNG) -> bool: def _ancestors_to_call( klass_node: nodes.ClassDef, method="__init__" -) -> Dict[nodes.ClassDef, bases.UnboundMethod]: +) -> dict[nodes.ClassDef, bases.UnboundMethod]: """Return a dictionary where keys are the list of base classes providing the queried method, and so that should/may be called from the method node """ - to_call: Dict[nodes.ClassDef, bases.UnboundMethod] = {} + to_call: dict[nodes.ClassDef, bases.UnboundMethod] = {} for base_node in klass_node.ancestors(recurs=False): try: to_call[base_node] = next(base_node.igetattr(method)) diff --git a/pylint/checkers/refactoring/__init__.py b/pylint/checkers/refactoring/__init__.py index 481845f925..d215dcee27 100644 --- a/pylint/checkers/refactoring/__init__.py +++ b/pylint/checkers/refactoring/__init__.py @@ -4,6 +4,7 @@ """Looks for code which can be refactored.""" +from __future__ import annotations from typing import TYPE_CHECKING @@ -25,7 +26,7 @@ ] -def register(linter: "PyLinter") -> None: +def register(linter: PyLinter) -> None: linter.register_checker(RefactoringChecker(linter)) linter.register_checker(NotChecker(linter)) linter.register_checker(RecommendationChecker(linter)) diff --git a/pylint/checkers/refactoring/implicit_booleaness_checker.py b/pylint/checkers/refactoring/implicit_booleaness_checker.py index 14d6b22b72..bea5a36077 100644 --- a/pylint/checkers/refactoring/implicit_booleaness_checker.py +++ b/pylint/checkers/refactoring/implicit_booleaness_checker.py @@ -2,7 +2,7 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt -from typing import List, Union +from __future__ import annotations import astroid from astroid import bases, nodes @@ -209,9 +209,7 @@ def _check_use_implicit_booleaness_not_comparison( ) @staticmethod - def base_names_of_instance( - node: Union[bases.Uninferable, bases.Instance] - ) -> List[str]: + def base_names_of_instance(node: bases.Uninferable | bases.Instance) -> list[str]: """Return all names inherited by a class instance or those returned by a function. The inherited names include 'object'. diff --git a/pylint/checkers/refactoring/recommendation_checker.py b/pylint/checkers/refactoring/recommendation_checker.py index 1fb7e72375..ef92a89ff7 100644 --- a/pylint/checkers/refactoring/recommendation_checker.py +++ b/pylint/checkers/refactoring/recommendation_checker.py @@ -2,7 +2,7 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt -from typing import Union +from __future__ import annotations import astroid from astroid import nodes @@ -322,7 +322,7 @@ def _check_consider_using_dict_items_comprehension( return def _check_use_sequence_for_iteration( - self, node: Union[nodes.For, nodes.Comprehension] + self, node: nodes.For | nodes.Comprehension ) -> None: """Check if code iterates over an in-place defined set.""" if isinstance(node.iter, nodes.Set): diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py index ce35af30d4..2e7d53f833 100644 --- a/pylint/checkers/refactoring/refactoring_checker.py +++ b/pylint/checkers/refactoring/refactoring_checker.py @@ -2,13 +2,15 @@ # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt +from __future__ import annotations + import collections import copy import itertools import sys import tokenize from functools import reduce -from typing import Dict, Iterator, List, NamedTuple, Optional, Tuple, Union +from typing import Iterator, NamedTuple import astroid from astroid import nodes @@ -61,7 +63,7 @@ def _if_statement_is_always_returning(if_node, returning_node_class) -> bool: return any(isinstance(node, returning_node_class) for node in if_node.body) -def _is_trailing_comma(tokens: List[tokenize.TokenInfo], index: int) -> bool: +def _is_trailing_comma(tokens: list[tokenize.TokenInfo], index: int) -> bool: """Check if the given token is a trailing comma. :param tokens: Sequence of modules tokens @@ -163,15 +165,15 @@ class ConsiderUsingWithStack(NamedTuple): if they are not used in a ``with`` block later on. """ - module_scope: Dict[str, nodes.NodeNG] = {} - class_scope: Dict[str, nodes.NodeNG] = {} - function_scope: Dict[str, nodes.NodeNG] = {} + module_scope: dict[str, nodes.NodeNG] = {} + class_scope: dict[str, nodes.NodeNG] = {} + function_scope: dict[str, nodes.NodeNG] = {} - def __iter__(self) -> Iterator[Dict[str, nodes.NodeNG]]: + def __iter__(self) -> Iterator[dict[str, nodes.NodeNG]]: yield from (self.function_scope, self.class_scope, self.module_scope) def get_stack_for_frame( - self, frame: Union[nodes.FunctionDef, nodes.ClassDef, nodes.Module] + self, frame: nodes.FunctionDef | nodes.ClassDef | nodes.Module ): """Get the stack corresponding to the scope of the given frame.""" if isinstance(frame, nodes.FunctionDef): @@ -1135,7 +1137,7 @@ def _emit_nested_blocks_message_if_needed(self, nested_blocks): args=(len(nested_blocks), self.linter.namespace.max_nested_blocks), ) - def _emit_consider_using_with_if_needed(self, stack: Dict[str, nodes.NodeNG]): + def _emit_consider_using_with_if_needed(self, stack: dict[str, nodes.NodeNG]): for node in stack.values(): self.add_message("consider-using-with", node=node) @@ -1623,7 +1625,7 @@ def _check_unnecessary_comprehension(self, node: nodes.Comprehension) -> None: else: return if expr_list == target_list and expr_list: - args: Optional[Tuple[str]] = None + args: tuple[str] | None = None inferred = utils.safe_infer(node.iter) if isinstance(node.parent, nodes.DictComp) and isinstance( inferred, astroid.objects.DictItems @@ -1878,7 +1880,7 @@ def _check_return_at_the_end(self, node): self.add_message("useless-return", node=node) def _check_unnecessary_dict_index_lookup( - self, node: Union[nodes.For, nodes.Comprehension] + self, node: nodes.For | nodes.Comprehension ) -> None: """Add message when accessing dict values by index lookup.""" # Verify that we have an .items() call and @@ -1981,7 +1983,7 @@ def _check_unnecessary_dict_index_lookup( ) def _check_unnecessary_list_index_lookup( - self, node: Union[nodes.For, nodes.Comprehension] + self, node: nodes.For | nodes.Comprehension ) -> None: if ( not isinstance(node.iter, nodes.Call)