summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
Diffstat (limited to 'pylint')
-rw-r--r--pylint/checkers/classes/class_checker.py22
-rw-r--r--pylint/extensions/code_style.py21
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)