diff options
author | Jacob Walls <jacobtylerwalls@gmail.com> | 2023-05-16 08:25:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-16 14:25:25 +0200 |
commit | 60daec60011d0b3a6be52c9410d1d7ef0179349d (patch) | |
tree | 5bb1d73eb9f8af22ba731a0a64f7bf8f10ba562c /pylint | |
parent | d7baf5d43fa8de68c4c169f731ae5af43ce60790 (diff) | |
download | pylint-git-main.tar.gz |
Closes #8660
Diffstat (limited to 'pylint')
-rw-r--r-- | pylint/checkers/classes/class_checker.py | 22 | ||||
-rw-r--r-- | pylint/extensions/code_style.py | 21 |
2 files changed, 35 insertions, 8 deletions
diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 77a795bcb..bdfb0968a 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -6,13 +6,12 @@ from __future__ import annotations -import collections from collections import defaultdict from collections.abc import Callable, Sequence from functools import cached_property from itertools import chain, zip_longest from re import Pattern -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any, NamedTuple, Union import astroid from astroid import bases, nodes, util @@ -63,12 +62,19 @@ ASTROID_TYPE_COMPARATORS = { # Dealing with useless override detection, with regard # to parameters vs arguments -_CallSignature = collections.namedtuple( - "_CallSignature", "args kws starred_args starred_kws" -) -_ParameterSignature = collections.namedtuple( - "_ParameterSignature", "args kwonlyargs varargs kwargs" -) + +class _CallSignature(NamedTuple): + args: list[str | None] + kws: dict[str | None, str | None] + starred_args: list[str] + starred_kws: list[str] + + +class _ParameterSignature(NamedTuple): + args: list[str] + kwonlyargs: list[str] + varargs: str + kwargs: str def _signature_from_call(call: nodes.Call) -> _CallSignature: diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index 5ce1ae476..622601c75 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -69,6 +69,17 @@ class CodeStyleChecker(BaseChecker): "default_enabled": False, }, ), + "R6105": ( + "Prefer 'typing.NamedTuple' over 'collections.namedtuple'", + "prefer-typing-namedtuple", + "'typing.NamedTuple' uses the well-known 'class' keyword " + "with type-hints for readability (it's also faster as it avoids " + "an internal exec call).\n" + "Disabled by default!", + { + "default_enabled": False, + }, + ), } options = ( ( @@ -89,12 +100,22 @@ class CodeStyleChecker(BaseChecker): def open(self) -> None: py_version = self.linter.config.py_version + self._py36_plus = py_version >= (3, 6) self._py38_plus = py_version >= (3, 8) self._max_length: int = ( self.linter.config.max_line_length_suggestions or self.linter.config.max_line_length ) + @only_required_for_messages("prefer-typing-namedtuple") + def visit_call(self, node: nodes.Call) -> None: + if self._py36_plus: + called = safe_infer(node.func) + if called and called.qname() == "collections.namedtuple": + self.add_message( + "prefer-typing-namedtuple", node=node, confidence=INFERENCE + ) + @only_required_for_messages("consider-using-namedtuple-or-dataclass") def visit_dict(self, node: nodes.Dict) -> None: self._check_dict_consider_namedtuple_dataclass(node) |