aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2021-09-03 13:47:23 +0200
committerGitHub <noreply@github.com>2021-09-03 13:47:23 +0200
commitbaaa81a2994cdd517fbde8693b0a4b0a67f5a4e3 (patch)
treec8b26e345fb3c7377a6c8e3a2b7afca28e1806e5
parent0981d8bec52f0917168e0e89947fe164f58be683 (diff)
downloadpylint-baaa81a2994cdd517fbde8693b0a4b0a67f5a4e3.tar.gz
Refactor various typing related issues (#4940)
* Add type annotations to ``visit`` & ``leave`` calls This adds typing to most calls that visit nodes. All other changes are due to mypy errors resulting from introduction of typing. * Fix outstanding mypy issues This removes some of the `type: ignore` comments in favour of solving the mypy issues these comments were surpressing. * Fix remaining references to node_classes Except for two references to node_classes in the changelog this should be the last of them Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r--doc/how_tos/custom_checkers.rst16
-rw-r--r--pylint/checkers/async.py4
-rw-r--r--pylint/checkers/base.py105
-rw-r--r--pylint/checkers/classes.py14
-rw-r--r--pylint/checkers/deprecated.py9
-rw-r--r--pylint/checkers/design_analysis.py22
-rw-r--r--pylint/checkers/exceptions.py56
-rw-r--r--pylint/checkers/format.py2
-rw-r--r--pylint/checkers/imports.py25
-rw-r--r--pylint/checkers/logging.py26
-rw-r--r--pylint/checkers/newstyle.py2
-rw-r--r--pylint/checkers/refactoring/len_checker.py4
-rw-r--r--pylint/checkers/refactoring/not_checker.py2
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py24
-rw-r--r--pylint/checkers/similar.py4
-rw-r--r--pylint/checkers/spelling.py8
-rw-r--r--pylint/checkers/stdlib.py18
-rw-r--r--pylint/checkers/strings.py28
-rw-r--r--pylint/checkers/typecheck.py62
-rw-r--r--pylint/checkers/utils.py27
-rw-r--r--pylint/checkers/variables.py52
-rw-r--r--pylint/extensions/bad_builtin.py2
-rw-r--r--pylint/extensions/broad_try_clause.py8
-rw-r--r--pylint/extensions/check_elif.py8
-rw-r--r--pylint/extensions/code_style.py6
-rw-r--r--pylint/extensions/comparetozero.py7
-rw-r--r--pylint/extensions/confusing_elif.py2
-rw-r--r--pylint/extensions/docparams.py13
-rw-r--r--pylint/extensions/docstyle.py8
-rw-r--r--pylint/extensions/emptystring.py6
-rw-r--r--pylint/extensions/mccabe.py3
-rw-r--r--pylint/extensions/overlapping_exceptions.py7
-rw-r--r--pylint/extensions/redefined_variable_type.py12
-rw-r--r--pylint/extensions/typing.py4
-rw-r--r--pylint/extensions/while_used.py4
-rw-r--r--pylint/graph.py4
-rw-r--r--pylint/message/message_id_store.py7
-rw-r--r--pylint/pyreverse/diadefslib.py17
-rw-r--r--pylint/pyreverse/inspector.py73
-rw-r--r--pylint/pyreverse/main.py2
-rw-r--r--pylint/testutils/reporter_for_tests.py4
-rw-r--r--setup.cfg1
-rw-r--r--tests/extensions/test_check_docs.py2
-rw-r--r--tests/functional/g/generated_members.py4
-rw-r--r--tests/functional/g/generated_members.rc2
-rw-r--r--tests/functional/u/unused/unused_variable.py4
-rw-r--r--tests/pyreverse/test_utils.py4
47 files changed, 375 insertions, 349 deletions
diff --git a/doc/how_tos/custom_checkers.rst b/doc/how_tos/custom_checkers.rst
index add8e1a69..c5deddd94 100644
--- a/doc/how_tos/custom_checkers.rst
+++ b/doc/how_tos/custom_checkers.rst
@@ -36,9 +36,11 @@ Firstly we will need to fill in some required boilerplate:
.. code-block:: python
import astroid
+ from astroid import nodes
from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker
+ from pylint.lint import PyLinter
class UniqueReturnChecker(BaseChecker):
__implements__ = IAstroidChecker
@@ -117,14 +119,14 @@ Next we'll track when we enter and leave a function.
.. code-block:: python
- def __init__(self, linter=None):
+ def __init__(self, linter: PyLinter =None) -> None:
super(UniqueReturnChecker, self).__init__(linter)
self._function_stack = []
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.append([])
- def leave_functiondef(self, node):
+ def leave_functiondef(self, node: nodes.FunctionDef) -> None:
self._function_stack.pop()
In the constructor we initialise a stack to keep a list of return nodes
@@ -138,13 +140,13 @@ and to remove the list of return nodes when we leave the function.
Finally we'll implement the check.
We will define a ``visit_return`` function,
-which is called with a :class:`.astroid.node_classes.Return` node.
+which is called with a :class:`.astroid.nodes.Return` node.
.. _astroid_extract_node:
.. TODO We can shorten/remove this bit once astroid has API docs.
We'll need to be able to figure out what attributes a
-:class:`.astroid.node_classes.Return` node has available.
+:class:`.astroid.nodes.Return` node has available.
We can use :func:`astroid.extract_node` for this::
>>> node = astroid.extract_node("return 5")
@@ -178,8 +180,8 @@ Now we know how to use the astroid node, we can implement our check.
.. code-block:: python
- def visit_return(self, node):
- if not isinstance(node.value, astroid.node_classes.Const):
+ def visit_return(self, node: nodes.Return) -> None:
+ if not isinstance(node.value, nodes.Const):
return
for other_return in self._function_stack[-1]:
diff --git a/pylint/checkers/async.py b/pylint/checkers/async.py
index a6831b394..939678d3e 100644
--- a/pylint/checkers/async.py
+++ b/pylint/checkers/async.py
@@ -46,7 +46,7 @@ class AsyncChecker(checkers.BaseChecker):
self._async_generators = ["contextlib.asynccontextmanager"]
@checker_utils.check_messages("yield-inside-async-function")
- def visit_asyncfunctiondef(self, node):
+ def visit_asyncfunctiondef(self, node: nodes.AsyncFunctionDef) -> None:
for child in node.nodes_of_class(nodes.Yield):
if child.scope() is node and (
sys.version_info[:2] == (3, 5) or isinstance(child, nodes.YieldFrom)
@@ -54,7 +54,7 @@ class AsyncChecker(checkers.BaseChecker):
self.add_message("yield-inside-async-function", node=child)
@checker_utils.check_messages("not-async-context-manager")
- def visit_asyncwith(self, node):
+ def visit_asyncwith(self, node: nodes.AsyncWith) -> None:
for ctx_mgr, _ in node.items:
inferred = checker_utils.safe_infer(ctx_mgr)
if inferred is None or inferred is astroid.Uninferable:
diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py
index f37752ac9..2ca79453a 100644
--- a/pylint/checkers/base.py
+++ b/pylint/checkers/base.py
@@ -66,7 +66,7 @@ import collections
import itertools
import re
import sys
-from typing import Optional, Pattern
+from typing import Any, Iterator, Optional, Pattern
import astroid
from astroid import nodes
@@ -565,7 +565,7 @@ class BasicErrorChecker(_BasicChecker):
}
@utils.check_messages("function-redefined")
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
self._check_redefinition("class", node)
def _too_many_starred_for_tuple(self, assign_tuple):
@@ -578,7 +578,7 @@ class BasicErrorChecker(_BasicChecker):
return starred_count > 1
@utils.check_messages("too-many-star-expressions", "invalid-star-assignment-target")
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
# Check *a, *b = ...
assign_target = node.targets[0]
# Check *a = b
@@ -591,7 +591,7 @@ class BasicErrorChecker(_BasicChecker):
self.add_message("too-many-star-expressions", node=node)
@utils.check_messages("star-needs-assignment-target")
- def visit_starred(self, node):
+ def visit_starred(self, node: nodes.Starred) -> None:
"""Check that a Starred expression is used in an assignment target."""
if isinstance(node.parent, nodes.Call):
# f(*args) is converted to Call(args=[Starred]), so ignore
@@ -617,7 +617,7 @@ class BasicErrorChecker(_BasicChecker):
"nonlocal-and-global",
"used-prior-global-declaration",
)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._check_nonlocal_and_global(node)
self._check_name_used_prior_global(node)
if not redefined_by_decorator(
@@ -638,7 +638,7 @@ class BasicErrorChecker(_BasicChecker):
self.add_message("return-in-init", node=node)
# Check for duplicate names by clustering args with same name for detailed report
arg_clusters = collections.defaultdict(list)
- arguments = filter(None, [node.args.args, node.args.kwonlyargs])
+ arguments: Iterator[Any] = filter(None, [node.args.args, node.args.kwonlyargs])
for arg in itertools.chain.from_iterable(arguments):
arg_clusters[arg.name].append(arg)
@@ -712,36 +712,36 @@ class BasicErrorChecker(_BasicChecker):
self.add_message("nonlocal-and-global", args=(name,), node=node)
@utils.check_messages("return-outside-function")
- def visit_return(self, node):
+ def visit_return(self, node: nodes.Return) -> None:
if not isinstance(node.frame(), nodes.FunctionDef):
self.add_message("return-outside-function", node=node)
@utils.check_messages("yield-outside-function")
- def visit_yield(self, node):
+ def visit_yield(self, node: nodes.Yield) -> None:
self._check_yield_outside_func(node)
@utils.check_messages("yield-outside-function")
- def visit_yieldfrom(self, node):
+ def visit_yieldfrom(self, node: nodes.YieldFrom) -> None:
self._check_yield_outside_func(node)
@utils.check_messages("not-in-loop", "continue-in-finally")
- def visit_continue(self, node):
+ def visit_continue(self, node: nodes.Continue) -> None:
self._check_in_loop(node, "continue")
@utils.check_messages("not-in-loop")
- def visit_break(self, node):
+ def visit_break(self, node: nodes.Break) -> None:
self._check_in_loop(node, "break")
@utils.check_messages("useless-else-on-loop")
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
self._check_else_on_loop(node)
@utils.check_messages("useless-else-on-loop")
- def visit_while(self, node):
+ def visit_while(self, node: nodes.While) -> None:
self._check_else_on_loop(node)
@utils.check_messages("nonexistent-operator")
- def visit_unaryop(self, node):
+ def visit_unaryop(self, node: nodes.UnaryOp) -> None:
"""check use of the non-existent ++ and -- operator operator"""
if (
(node.op in "+-")
@@ -771,12 +771,12 @@ class BasicErrorChecker(_BasicChecker):
self.add_message("nonlocal-without-binding", args=(name,), node=node)
@utils.check_messages("nonlocal-without-binding")
- def visit_nonlocal(self, node):
+ def visit_nonlocal(self, node: nodes.Nonlocal) -> None:
for name in node.names:
self._check_nonlocal_without_binding(node, name)
@utils.check_messages("abstract-class-instantiated")
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
"""Check instantiating abstract class with
abc.ABCMeta as metaclass.
"""
@@ -1091,15 +1091,15 @@ class BasicChecker(_BasicChecker):
self.stats = self.linter.add_stats(module=0, function=0, method=0, class_=0)
@utils.check_messages("using-constant-test", "missing-parentheses-for-call-in-test")
- def visit_if(self, node):
+ def visit_if(self, node: nodes.If) -> None:
self._check_using_constant_test(node, node.test)
@utils.check_messages("using-constant-test", "missing-parentheses-for-call-in-test")
- def visit_ifexp(self, node):
+ def visit_ifexp(self, node: nodes.IfExp) -> None:
self._check_using_constant_test(node, node.test)
@utils.check_messages("using-constant-test", "missing-parentheses-for-call-in-test")
- def visit_comprehension(self, node):
+ def visit_comprehension(self, node: nodes.Comprehension) -> None:
if node.ifs:
for if_test in node.ifs:
self._check_using_constant_test(node, if_test)
@@ -1157,11 +1157,11 @@ class BasicChecker(_BasicChecker):
pass
self.add_message("using-constant-test", node=node)
- def visit_module(self, _):
+ def visit_module(self, _: nodes.Module) -> None:
"""check module name, docstring and required arguments"""
self.stats["module"] += 1
- def visit_classdef(self, node): # pylint: disable=unused-argument
+ def visit_classdef(self, _: nodes.ClassDef) -> None:
"""check module name, docstring and redefinition
increment branch counter
"""
@@ -1170,7 +1170,7 @@ class BasicChecker(_BasicChecker):
@utils.check_messages(
"pointless-statement", "pointless-string-statement", "expression-not-assigned"
)
- def visit_expr(self, node):
+ def visit_expr(self, node: nodes.Expr) -> None:
"""Check for various kind of statements without effect"""
expr = node.value
if isinstance(expr, nodes.Const) and isinstance(expr.value, str):
@@ -1240,7 +1240,7 @@ class BasicChecker(_BasicChecker):
return False
@utils.check_messages("unnecessary-lambda")
- def visit_lambda(self, node):
+ def visit_lambda(self, node: nodes.Lambda) -> None:
"""check whether or not the lambda is suspicious"""
# if the body of the lambda is a call expression with the same
# argument list as the lambda itself, then the lambda is
@@ -1300,7 +1300,7 @@ class BasicChecker(_BasicChecker):
self.add_message("unnecessary-lambda", line=node.fromlineno, node=node)
@utils.check_messages("dangerous-default-value")
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""check function name, docstring, arguments, redefinition,
variable names, max locals
"""
@@ -1350,7 +1350,7 @@ class BasicChecker(_BasicChecker):
self.add_message("dangerous-default-value", node=node, args=(msg,))
@utils.check_messages("unreachable", "lost-exception")
- def visit_return(self, node):
+ def visit_return(self, node: nodes.Return) -> None:
"""1 - check is the node has a right sibling (if so, that's some
unreachable code)
2 - check is the node is inside the finally clause of a try...finally
@@ -1361,14 +1361,14 @@ class BasicChecker(_BasicChecker):
self._check_not_in_finally(node, "return", (nodes.FunctionDef,))
@utils.check_messages("unreachable")
- def visit_continue(self, node):
+ def visit_continue(self, node: nodes.Continue) -> None:
"""check is the node has a right sibling (if so, that's some unreachable
code)
"""
self._check_unreachable(node)
@utils.check_messages("unreachable", "lost-exception")
- def visit_break(self, node):
+ def visit_break(self, node: nodes.Break) -> None:
"""1 - check is the node has a right sibling (if so, that's some
unreachable code)
2 - check is the node is inside the finally clause of a try...finally
@@ -1380,7 +1380,7 @@ class BasicChecker(_BasicChecker):
self._check_not_in_finally(node, "break", (nodes.For, nodes.While))
@utils.check_messages("unreachable")
- def visit_raise(self, node):
+ def visit_raise(self, node: nodes.Raise) -> None:
"""check if the node has a right sibling (if so, that's some unreachable
code)
"""
@@ -1410,7 +1410,7 @@ class BasicChecker(_BasicChecker):
@utils.check_messages(
"eval-used", "exec-used", "bad-reversed-sequence", "misplaced-format-function"
)
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
"""visit a Call node -> check if this is not a disallowed builtin
call and check for * or ** use
"""
@@ -1428,7 +1428,7 @@ class BasicChecker(_BasicChecker):
self.add_message("eval-used", node=node)
@utils.check_messages("assert-on-tuple", "assert-on-string-literal")
- def visit_assert(self, node):
+ def visit_assert(self, node: nodes.Assert) -> None:
"""check whether assert is used on a tuple or string literal."""
if (
node.fail is None
@@ -1445,7 +1445,7 @@ class BasicChecker(_BasicChecker):
self.add_message("assert-on-string-literal", node=node, args=(when,))
@utils.check_messages("duplicate-key")
- def visit_dict(self, node):
+ def visit_dict(self, node: nodes.Dict) -> None:
"""check duplicate key in dictionary"""
keys = set()
for k, _ in node.items:
@@ -1455,11 +1455,11 @@ class BasicChecker(_BasicChecker):
self.add_message("duplicate-key", node=node, args=key)
keys.add(key)
- def visit_tryfinally(self, node):
+ def visit_tryfinally(self, node: nodes.TryFinally) -> None:
"""update try...finally flag"""
self._tryfinallys.append(node)
- def leave_tryfinally(self, node): # pylint: disable=unused-argument
+ def leave_tryfinally(self, _: nodes.TryFinally) -> None:
"""update try...finally flag"""
self._tryfinallys.pop()
@@ -1554,7 +1554,7 @@ class BasicChecker(_BasicChecker):
self.add_message("bad-reversed-sequence", node=node)
@utils.check_messages("confusing-with-statement")
- def visit_with(self, node):
+ def visit_with(self, node: nodes.With) -> None:
# a "with" statement with multiple managers corresponds
# to one AST "With" node with multiple items
pairs = node.items
@@ -1636,12 +1636,12 @@ class BasicChecker(_BasicChecker):
)
@utils.check_messages("self-assigning-variable", "redeclared-assigned-name")
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
self._check_self_assigning_variable(node)
self._check_redeclared_assign_name(node.targets)
@utils.check_messages("redeclared-assigned-name")
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
self._check_redeclared_assign_name([node.target])
@@ -1892,11 +1892,11 @@ class NameChecker(_BasicChecker):
return regexps, hints
@utils.check_messages("disallowed-name", "invalid-name", "non-ascii-name")
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
self._check_name("module", node.name.split(".")[-1], node)
self._bad_names = {}
- def leave_module(self, node): # pylint: disable=unused-argument
+ def leave_module(self, _: nodes.Module) -> None:
for all_groups in self._bad_names.values():
if len(all_groups) < 2:
continue
@@ -1915,12 +1915,12 @@ class NameChecker(_BasicChecker):
else:
warnings = groups[min_warnings][0]
for args in warnings:
- self._raise_name_warning(*args, prevalent_group=prevalent_group)
+ self._raise_name_warning(prevalent_group, *args)
@utils.check_messages(
"disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name"
)
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
self._check_assign_to_new_keyword_violation(node.name, node)
self._check_name("class", node.name, node)
for attr, anodes in node.instance_attrs.items():
@@ -1930,7 +1930,7 @@ class NameChecker(_BasicChecker):
@utils.check_messages(
"disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name"
)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
# Do not emit any warnings if the method is just an implementation
# of a base class method.
self._check_assign_to_new_keyword_violation(node.name, node)
@@ -1958,14 +1958,14 @@ class NameChecker(_BasicChecker):
visit_asyncfunctiondef = visit_functiondef
@utils.check_messages("disallowed-name", "invalid-name", "non-ascii-name")
- def visit_global(self, node):
+ def visit_global(self, node: nodes.Global) -> None:
for name in node.names:
self._check_name("const", name, node)
@utils.check_messages(
"disallowed-name", "invalid-name", "assign-to-new-keyword", "non-ascii-name"
)
- def visit_assignname(self, node):
+ def visit_assignname(self, node: nodes.AssignName) -> None:
"""check module level assigned names"""
self._check_assign_to_new_keyword_violation(node.name, node)
frame = node.frame()
@@ -2017,12 +2017,12 @@ class NameChecker(_BasicChecker):
def _raise_name_warning(
self,
+ prevalent_group: Optional[str],
node: nodes.NodeNG,
node_type: str,
name: str,
confidence,
warning: str = "invalid-name",
- prevalent_group: Optional[str] = None,
) -> None:
type_label = HUMAN_READABLE_TYPES[node_type]
hint = self._name_hints[node_type]
@@ -2057,7 +2057,7 @@ class NameChecker(_BasicChecker):
non_ascii_match = self._non_ascii_rgx_compiled.match(name)
if non_ascii_match is not None:
self._raise_name_warning(
- node, node_type, name, confidence, warning="non-ascii-name"
+ None, node, node_type, name, confidence, warning="non-ascii-name"
)
def _should_exempt_from_invalid_name(node):
@@ -2083,7 +2083,7 @@ class NameChecker(_BasicChecker):
warnings.append((node, node_type, name, confidence))
if match is None and not _should_exempt_from_invalid_name(node):
- self._raise_name_warning(node, node_type, name, confidence)
+ self._raise_name_warning(None, node, node_type, name, confidence)
def _check_assign_to_new_keyword_violation(self, name, node):
keyword_first_version = self._name_became_keyword_in_version(
@@ -2172,16 +2172,16 @@ class DocStringChecker(_BasicChecker):
)
@utils.check_messages("missing-docstring", "empty-docstring")
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
self._check_docstring("module", node)
@utils.check_messages("missing-docstring", "empty-docstring")
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
if self.config.no_docstring_rgx.match(node.name) is None:
self._check_docstring("class", node)
@utils.check_messages("missing-docstring", "empty-docstring")
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
if self.config.no_docstring_rgx.match(node.name) is None:
ftype = "method" if node.is_method() else "function"
if (
@@ -2276,7 +2276,7 @@ class PassChecker(_BasicChecker):
}
@utils.check_messages("unnecessary-pass")
- def visit_pass(self, node):
+ def visit_pass(self, node: nodes.Pass) -> None:
if len(node.parent.child_sequence(node)) > 1 or (
isinstance(node.parent, (nodes.ClassDef, nodes.FunctionDef))
and (node.parent.doc is not None)
@@ -2486,10 +2486,9 @@ class ComparisonChecker(_BasicChecker):
suggestion = f"{right.as_string()} {operator} {left.value!r}"
self.add_message("misplaced-comparison-constant", node=node, args=(suggestion,))
- def _check_logical_tautology(self, node):
+ def _check_logical_tautology(self, node: nodes.Compare):
"""Check if identifier is compared against itself.
:param node: Compare node
- :type node: astroid.node_classes.Compare
:Example:
val = 786
if val == val: # [comparison-with-itself]
@@ -2540,7 +2539,7 @@ class ComparisonChecker(_BasicChecker):
"comparison-with-itself",
"comparison-with-callable",
)
- def visit_compare(self, node):
+ def visit_compare(self, node: nodes.Compare) -> None:
self._check_callable_comparison(node)
self._check_logical_tautology(node)
self._check_unidiomatic_typecheck(node)
diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py
index 0b37a9f53..59e474220 100644
--- a/pylint/checkers/classes.py
+++ b/pylint/checkers/classes.py
@@ -845,7 +845,7 @@ a metaclass class method.",
"inconsistent-mro",
"duplicate-bases",
)
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
"""init visit variable _accessed"""
self._check_bases_classes(node)
# if not an exception or a metaclass
@@ -1092,7 +1092,7 @@ a metaclass class method.",
"attribute-defined-outside-init", args=attr, node=node
)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""check method arguments, overriding"""
# ignore actual functions
if not node.is_method():
@@ -1400,7 +1400,7 @@ a metaclass class method.",
"class-variable-slots-conflict", args=(inferred.value,), node=elt
)
- def leave_functiondef(self, node):
+ def leave_functiondef(self, node: nodes.FunctionDef) -> None:
"""on method node, check if this method couldn't be a function
ignore class, static and abstract methods, initializer,
@@ -1427,7 +1427,7 @@ a metaclass class method.",
):
self.add_message("no-self-use", node=node)
- def visit_attribute(self, node):
+ def visit_attribute(self, node: nodes.Attribute) -> None:
"""check if the getattr is an access to a class member
if so, register it. Also check for access to protected
class member from outside its class (but ignore __special__
@@ -1514,7 +1514,7 @@ a metaclass class method.",
@check_messages(
"protected-access", "no-classmethod-decorator", "no-staticmethod-decorator"
)
- def visit_assign(self, assign_node):
+ def visit_assign(self, assign_node: nodes.Assign) -> None:
self._check_classmethod_declaration(assign_node)
node = assign_node.targets[0]
if not isinstance(node, nodes.AssignAttr):
@@ -1701,7 +1701,7 @@ a metaclass class method.",
except astroid.NotFoundError:
return False
- def visit_name(self, node):
+ def visit_name(self, node: nodes.Name) -> None:
"""check if the name handle an access to a class member
if so, register it
"""
@@ -2154,7 +2154,7 @@ class SpecialMethodsChecker(BaseChecker):
"invalid-getnewargs-returned",
"invalid-getnewargs-ex-returned",
)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
if not node.is_method():
return
diff --git a/pylint/checkers/deprecated.py b/pylint/checkers/deprecated.py
index 381d5dac6..ac1cd6425 100644
--- a/pylint/checkers/deprecated.py
+++ b/pylint/checkers/deprecated.py
@@ -9,6 +9,7 @@ import astroid
from astroid import nodes
from pylint.checkers import utils
+from pylint.checkers.base_checker import BaseChecker
from pylint.checkers.utils import get_import_name, infer_all, safe_infer
ACCEPTABLE_NODES = (
@@ -19,7 +20,7 @@ ACCEPTABLE_NODES = (
)
-class DeprecatedMixin:
+class DeprecatedMixin(BaseChecker):
"""A mixin implementing logic for checking deprecated symbols.
A class implementing mixin must define "deprecated-method" Message.
"""
@@ -68,7 +69,7 @@ class DeprecatedMixin:
"deprecated-module",
"deprecated-class",
)
- def visit_import(self, node):
+ def visit_import(self, node: nodes.Import) -> None:
"""triggered when an import statement is seen"""
for name in (name for name, _ in node.names):
self.check_deprecated_module(node, name)
@@ -87,7 +88,7 @@ class DeprecatedMixin:
return ()
@utils.check_messages("deprecated-decorator")
- def visit_decorators(self, node):
+ def visit_decorators(self, node: nodes.Decorators) -> None:
"""Triggered when a decorator statement is seen"""
children = list(node.get_children())
if not children:
@@ -104,7 +105,7 @@ class DeprecatedMixin:
"deprecated-module",
"deprecated-class",
)
- def visit_importfrom(self, node):
+ def visit_importfrom(self, node: nodes.ImportFrom) -> None:
"""triggered when a from statement is seen"""
basename = node.modname
basename = get_import_name(node, basename)
diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py
index dbc132be4..9777b568e 100644
--- a/pylint/checkers/design_analysis.py
+++ b/pylint/checkers/design_analysis.py
@@ -264,7 +264,7 @@ def _get_parents(
if parent.qname() in ignored_parents:
continue
parents.add(parent)
- to_explore.extend(parent.ancestors(recurs=False)) # type: ignore
+ to_explore.extend(parent.ancestors(recurs=False))
return parents
@@ -417,7 +417,7 @@ class MisdesignChecker(BaseChecker):
"too-few-public-methods",
"too-many-public-methods",
)
- def visit_classdef(self, node: nodes.ClassDef):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
"""check size of inheritance hierarchy and number of instance attributes"""
parents = _get_parents(
node, STDLIB_CLASSES_IGNORE_ANCESTOR.union(self.config.ignored_parents)
@@ -438,7 +438,7 @@ class MisdesignChecker(BaseChecker):
)
@check_messages("too-few-public-methods", "too-many-public-methods")
- def leave_classdef(self, node):
+ def leave_classdef(self, node: nodes.ClassDef) -> None:
"""check number of public methods"""
my_methods = sum(
1 for method in node.mymethods() if not method.name.startswith("_")
@@ -482,7 +482,7 @@ class MisdesignChecker(BaseChecker):
"too-many-statements",
"keyword-arg-before-vararg",
)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""check function name, docstring, arguments, redefinition,
variable names, max locals
"""
@@ -525,7 +525,7 @@ class MisdesignChecker(BaseChecker):
"too-many-locals",
"too-many-statements",
)
- def leave_functiondef(self, node):
+ def leave_functiondef(self, node: nodes.FunctionDef) -> None:
"""most of the work is done here on close:
checks for max returns, branch, return in __init__
"""
@@ -554,20 +554,20 @@ class MisdesignChecker(BaseChecker):
leave_asyncfunctiondef = leave_functiondef
- def visit_return(self, _):
+ def visit_return(self, _: nodes.Return) -> None:
"""count number of returns"""
if not self._returns:
return # return outside function, reported by the base checker
self._returns[-1] += 1
- def visit_default(self, node):
+ def visit_default(self, node: nodes.NodeNG) -> None:
"""default visit method -> increments the statements counter if
necessary
"""
if node.is_statement:
self._inc_all_stmts(1)
- def visit_tryexcept(self, node):
+ def visit_tryexcept(self, node: nodes.TryExcept) -> None:
"""increments the branches counter"""
branches = len(node.handlers)
if node.orelse:
@@ -575,13 +575,13 @@ class MisdesignChecker(BaseChecker):
self._inc_branch(node, branches)
self._inc_all_stmts(branches)
- def visit_tryfinally(self, node):
+ def visit_tryfinally(self, node: nodes.TryFinally) -> None:
"""increments the branches counter"""
self._inc_branch(node, 2)
self._inc_all_stmts(2)
@check_messages("too-many-boolean-expressions")
- def visit_if(self, node):
+ def visit_if(self, node: nodes.If) -> None:
"""increments the branches counter and checks boolean expressions"""
self._check_boolean_expressions(node)
branches = 1
@@ -609,7 +609,7 @@ class MisdesignChecker(BaseChecker):
args=(nb_bool_expr, self.config.max_bool_expr),
)
- def visit_while(self, node):
+ def visit_while(self, node: nodes.While) -> None:
"""increments the branches counter"""
branches = 1
if node.orelse:
diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py
index e3443c85f..7c09be3f7 100644
--- a/pylint/checkers/exceptions.py
+++ b/pylint/checkers/exceptions.py
@@ -34,10 +34,10 @@
"""Checks for various exception related errors."""
import builtins
import inspect
-import typing
+from typing import Any, List, Optional
import astroid
-from astroid import nodes
+from astroid import nodes, objects
from pylint import checkers, interfaces
from pylint.checkers import utils
@@ -70,7 +70,7 @@ def _annotated_unpack_infer(stmt, context=None):
yield stmt, inferred
-def _is_raising(body: typing.List) -> bool:
+def _is_raising(body: List) -> bool:
"""Return true if the given statement node raise an exception"""
for node in body:
if isinstance(node, nodes.Raise):
@@ -201,26 +201,26 @@ class BaseVisitor:
else:
self.visit_default(node)
- def visit_default(self, node): # pylint: disable=unused-argument
+ def visit_default(self, _: nodes.NodeNG) -> None:
"""Default implementation for all the nodes."""
class ExceptionRaiseRefVisitor(BaseVisitor):
"""Visit references (anything that is not an AST leaf)."""
- def visit_name(self, name):
- if name.name == "NotImplemented":
+ def visit_name(self, node: nodes.Name) -> None:
+ if node.name == "NotImplemented":
self._checker.add_message("notimplemented-raised", node=self._node)
- def visit_call(self, call):
- if isinstance(call.func, nodes.Name):
- self.visit_name(call.func)
+ def visit_call(self, node: nodes.Call) -> None:
+ if isinstance(node.func, nodes.Name):
+ self.visit_name(node.func)
if (
- len(call.args) > 1
- and isinstance(call.args[0], nodes.Const)
- and isinstance(call.args[0].value, str)
+ len(node.args) > 1
+ and isinstance(node.args[0], nodes.Const)
+ and isinstance(node.args[0].value, str)
):
- msg = call.args[0].value
+ msg = node.args[0].value
if "%" in msg or ("{" in msg and "}" in msg):
self._checker.add_message("raising-format-tuple", node=self._node)
@@ -228,12 +228,12 @@ class ExceptionRaiseRefVisitor(BaseVisitor):
class ExceptionRaiseLeafVisitor(BaseVisitor):
"""Visitor for handling leaf kinds of a raise value."""
- def visit_const(self, const):
+ def visit_const(self, node: nodes.Const) -> None:
self._checker.add_message(
- "raising-bad-type", node=self._node, args=const.value.__class__.__name__
+ "raising-bad-type", node=self._node, args=node.value.__class__.__name__
)
- def visit_instance(self, instance):
+ def visit_instance(self, instance: objects.ExceptionInstance) -> None:
# pylint: disable=protected-access
cls = instance._proxied
self.visit_classdef(cls)
@@ -241,15 +241,15 @@ class ExceptionRaiseLeafVisitor(BaseVisitor):
# Exception instances have a particular class type
visit_exceptioninstance = visit_instance
- def visit_classdef(self, cls):
- if not utils.inherit_from_std_ex(cls) and utils.has_known_bases(cls):
- if cls.newstyle:
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
+ if not utils.inherit_from_std_ex(node) and utils.has_known_bases(node):
+ if node.newstyle:
self._checker.add_message("raising-non-exception", node=self._node)
- def visit_tuple(self, _):
+ def visit_tuple(self, _: nodes.Tuple) -> None:
self._checker.add_message("raising-bad-type", node=self._node, args="tuple")
- def visit_default(self, node):
+ def visit_default(self, node: nodes.NodeNG) -> None:
name = getattr(node, "name", node.__class__.__name__)
self._checker.add_message("raising-bad-type", node=self._node, args=name)
@@ -289,7 +289,7 @@ class ExceptionsChecker(checkers.BaseChecker):
"raising-format-tuple",
"raise-missing-from",
)
- def visit_raise(self, node):
+ def visit_raise(self, node: nodes.Raise) -> None:
if node.exc is None:
self._check_misplaced_bare_raise(node)
return
@@ -428,8 +428,8 @@ class ExceptionsChecker(checkers.BaseChecker):
def _check_try_except_raise(self, node):
def gather_exceptions_from_handler(
handler,
- ) -> typing.Optional[typing.List[nodes.NodeNG]]:
- exceptions: typing.List[nodes.NodeNG] = []
+ ) -> Optional[List[nodes.NodeNG]]:
+ exceptions: List[nodes.NodeNG] = []
if handler.type:
exceptions_in_handler = utils.safe_infer(handler.type)
if isinstance(exceptions_in_handler, nodes.Tuple):
@@ -483,14 +483,14 @@ class ExceptionsChecker(checkers.BaseChecker):
self.add_message("try-except-raise", node=handler_having_bare_raise)
@utils.check_messages("wrong-exception-operation")
- def visit_binop(self, node):
+ def visit_binop(self, node: nodes.BinOp) -> None:
if isinstance(node.parent, nodes.ExceptHandler):
# except (V | A)
suggestion = f"Did you mean '({node.left.as_string()}, {node.right.as_string()})' instead?"
self.add_message("wrong-exception-operation", node=node, args=(suggestion,))
@utils.check_messages("wrong-exception-operation")
- def visit_compare(self, node):
+ def visit_compare(self, node: nodes.Compare) -> None:
if isinstance(node.parent, nodes.ExceptHandler):
# except (V < A)
suggestion = f"Did you mean '({node.left.as_string()}, {', '.join(operand.as_string() for _, operand in node.ops)})' instead?"
@@ -505,10 +505,10 @@ class ExceptionsChecker(checkers.BaseChecker):
"catching-non-exception",
"duplicate-except",
)
- def visit_tryexcept(self, node):
+ def visit_tryexcept(self, node: nodes.TryExcept) -> None:
"""check for empty except"""
self._check_try_except_raise(node)
- exceptions_classes = []
+ exceptions_classes: List[Any] = []
nb_handlers = len(node.handlers)
for index, handler in enumerate(node.handlers):
if handler.type is None:
diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py
index 1306070ba..ffd1b2169 100644
--- a/pylint/checkers/format.py
+++ b/pylint/checkers/format.py
@@ -582,7 +582,7 @@ class FormatChecker(BaseTokenChecker):
)
@check_messages("multiple-statements")
- def visit_default(self, node):
+ def visit_default(self, node: nodes.NodeNG) -> None:
"""check the node line number and check it if not yet done"""
if not node.is_statement:
return
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index d4d813812..7e0cda26d 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -50,7 +50,7 @@ import copy
import os
import sys
from distutils import sysconfig
-from typing import Dict, List, Set, Union
+from typing import Any, Dict, List, Set, Tuple, Union
import astroid
from astroid import nodes
@@ -66,6 +66,7 @@ from pylint.checkers.utils import (
from pylint.exceptions import EmptyReportError
from pylint.graph import DotBackend, get_cycles
from pylint.interfaces import IAstroidChecker
+from pylint.lint import PyLinter
from pylint.reporters.ureports.nodes import Paragraph, VerbatimText, VNode
from pylint.utils import IsortDriver, get_global_option
@@ -418,14 +419,18 @@ class ImportsChecker(DeprecatedMixin, BaseChecker):
),
)
- def __init__(self, linter=None):
+ def __init__(
+ self, linter: PyLinter = None
+ ): # pylint: disable=super-init-not-called # See https://github.com/PyCQA/pylint/issues/4941
BaseChecker.__init__(self, linter)
- self.stats = None
- self.import_graph = None
- self._imports_stack = []
+ self.stats: Dict[Any, Any] = {}
+ self.import_graph: collections.defaultdict = collections.defaultdict(set)
+ self._imports_stack: List[Tuple[Any, Any]] = []
self._first_non_import_node = None
- self._module_pkg = {} # mapping of modules to the pkg they belong in
- self._allow_any_import_level = set()
+ self._module_pkg: Dict[
+ Any, Any
+ ] = {} # mapping of modules to the pkg they belong in
+ self._allow_any_import_level: Set[Any] = set()
self.reports = (
("RP0401", "External dependencies", self._report_external_dependencies),
("RP0402", "Modules dependencies graph", self._report_dependencies_graph),
@@ -494,7 +499,7 @@ class ImportsChecker(DeprecatedMixin, BaseChecker):
return self.config.deprecated_modules
@check_messages(*MSGS)
- def visit_import(self, node):
+ def visit_import(self, node: nodes.Import) -> None:
"""triggered when an import statement is seen"""
self._check_reimport(node)
self._check_import_as_rename(node)
@@ -520,7 +525,7 @@ class ImportsChecker(DeprecatedMixin, BaseChecker):
self._add_imported_module(node, imported_module.name)
@check_messages(*MSGS)
- def visit_importfrom(self, node):
+ def visit_importfrom(self, node: nodes.ImportFrom) -> None:
"""triggered when a from statement is seen"""
basename = node.modname
imported_module = self._get_imported_module(node, basename)
@@ -618,7 +623,7 @@ class ImportsChecker(DeprecatedMixin, BaseChecker):
visit_ifexp
) = visit_comprehension = visit_expr = visit_if = compute_first_non_import_node
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
if not self.linter.is_message_enabled("wrong-import-position", node.fromlineno):
return
# If it is the first non import instruction of the module, record it.
diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py
index c54ef0340..3cbf20956 100644
--- a/pylint/checkers/logging.py
+++ b/pylint/checkers/logging.py
@@ -24,6 +24,7 @@
"""checker for use of Python logging
"""
import string
+from typing import Set
import astroid
from astroid import nodes
@@ -160,12 +161,12 @@ class LoggingChecker(checkers.BaseChecker):
),
)
- def visit_module(self, node): # pylint: disable=unused-argument
+ def visit_module(self, _: nodes.Module) -> None:
"""Clears any state left in this checker from last module checked."""
# The code being checked can just as easily "import logging as foo",
# so it is necessary to process the imports and store in this field
# what name the logging module is actually given.
- self._logging_names = set()
+ self._logging_names: Set[str] = set()
logging_mods = self.config.logging_modules
self._format_style = self.config.logging_format_style
@@ -177,7 +178,7 @@ class LoggingChecker(checkers.BaseChecker):
if len(parts) > 1:
self._from_imports[parts[0]] = parts[1]
- def visit_importfrom(self, node):
+ def visit_importfrom(self, node: nodes.ImportFrom) -> None:
"""Checks to see if a module uses a non-Python logging module."""
try:
logging_name = self._from_imports[node.modname]
@@ -187,14 +188,14 @@ class LoggingChecker(checkers.BaseChecker):
except KeyError:
pass
- def visit_import(self, node):
+ def visit_import(self, node: nodes.Import) -> None:
"""Checks to see if this module uses Python's built-in logging."""
for module, as_name in node.names:
if module in self._logging_modules:
self._logging_names.add(as_name or module)
@check_messages(*MSGS)
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
"""Checks calls to logging methods."""
def is_logging_name():
@@ -294,18 +295,15 @@ class LoggingChecker(checkers.BaseChecker):
"""
return isinstance(operand, nodes.Const) and operand.name == "str"
- def _check_call_func(self, node):
- """Checks that function call is not format_string.format().
-
- Args:
- node (astroid.node_classes.Call):
- Call AST node to be checked.
- """
+ def _check_call_func(self, node: nodes.Call):
+ """Checks that function call is not format_string.format()."""
func = utils.safe_infer(node.func)
types = ("str", "unicode")
methods = ("format",)
- if is_method_call(func, types, methods) and not is_complex_format_str(
- func.bound
+ if (
+ isinstance(func, astroid.BoundMethod)
+ and is_method_call(func, types, methods)
+ and not is_complex_format_str(func.bound)
):
self.add_message(
"logging-format-interpolation",
diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py
index 8c5ae5e83..0c63db232 100644
--- a/pylint/checkers/newstyle.py
+++ b/pylint/checkers/newstyle.py
@@ -56,7 +56,7 @@ class NewStyleConflictChecker(BaseChecker):
options = ()
@check_messages("bad-super-call")
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""check use of super"""
# ignore actual functions or method within a new style class
if not node.is_method():
diff --git a/pylint/checkers/refactoring/len_checker.py b/pylint/checkers/refactoring/len_checker.py
index 6b36681a2..4e4eb2b46 100644
--- a/pylint/checkers/refactoring/len_checker.py
+++ b/pylint/checkers/refactoring/len_checker.py
@@ -52,7 +52,7 @@ class LenChecker(checkers.BaseChecker):
options = ()
@utils.check_messages("len-as-condition")
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
# a len(S) call is used inside a test condition
# could be if, while, assert or if expression statement
# e.g. `if len(S):`
@@ -102,7 +102,7 @@ class LenChecker(checkers.BaseChecker):
return False
@utils.check_messages("len-as-condition")
- def visit_unaryop(self, node):
+ def visit_unaryop(self, node: nodes.UnaryOp) -> None:
"""`not len(S)` must become `not S` regardless if the parent block
is a test condition or something else (boolean expression)
e.g. `if not len(S):`"""
diff --git a/pylint/checkers/refactoring/not_checker.py b/pylint/checkers/refactoring/not_checker.py
index ebe2c0ebe..f8c670e96 100644
--- a/pylint/checkers/refactoring/not_checker.py
+++ b/pylint/checkers/refactoring/not_checker.py
@@ -42,7 +42,7 @@ class NotChecker(checkers.BaseChecker):
skipped_classnames = [f"builtins.{qname}" for qname in ("set", "frozenset")]
@utils.check_messages("unneeded-not")
- def visit_unaryop(self, node):
+ def visit_unaryop(self, node: nodes.UnaryOp) -> None:
if node.op != "not":
return
operand = node.operand
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 9ce42e395..7b977d39b 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -595,7 +595,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self.add_message("trailing-comma-tuple", line=token.start[0])
@utils.check_messages("consider-using-with")
- def leave_module(self, _):
+ def leave_module(self, _: nodes.Module) -> None:
# check for context managers that have been created but not used
self._emit_consider_using_with_if_needed(
self._consider_using_with_stack.module_scope
@@ -603,7 +603,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self._init()
@utils.check_messages("too-many-nested-blocks")
- def visit_tryexcept(self, node):
+ def visit_tryexcept(self, node: nodes.TryExcept) -> None:
self._check_nested_blocks(node)
visit_tryfinally = visit_tryexcept
@@ -635,7 +635,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"too-many-nested-blocks",
"unnecessary-dict-index-lookup",
)
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
self._check_nested_blocks(node)
self._check_unnecessary_dict_index_lookup(node)
@@ -643,12 +643,12 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self._check_redefined_argument_from_local(name)
@utils.check_messages("redefined-argument-from-local")
- def visit_excepthandler(self, node):
+ def visit_excepthandler(self, node: nodes.ExceptHandler) -> None:
if node.name and isinstance(node.name, nodes.AssignName):
self._check_redefined_argument_from_local(node.name)
@utils.check_messages("redefined-argument-from-local")
- def visit_with(self, node):
+ def visit_with(self, node: nodes.With) -> None:
for var, names in node.items:
if isinstance(var, nodes.Name):
for stack in self._consider_using_with_stack:
@@ -762,7 +762,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"no-else-continue",
"consider-using-get",
)
- def visit_if(self, node):
+ def visit_if(self, node: nodes.If) -> None:
self._check_simplifiable_if(node)
self._check_nested_blocks(node)
self._check_superfluous_else_return(node)
@@ -852,7 +852,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
)
@utils.check_messages("simplifiable-if-expression")
- def visit_ifexp(self, node):
+ def visit_ifexp(self, node: nodes.IfExp) -> None:
self._check_simplifiable_ifexp(node)
def _check_simplifiable_ifexp(self, node):
@@ -911,7 +911,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self._consider_using_with_stack.class_scope.clear()
@utils.check_messages("stop-iteration-return")
- def visit_raise(self, node):
+ def visit_raise(self, node: nodes.Raise) -> None:
self._check_stop_iteration_inside_generator(node)
def _check_stop_iteration_inside_generator(self, node):
@@ -990,7 +990,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"use-list-literal",
"use-dict-literal",
)
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
self._check_raising_stopiteration_in_generator_next_call(node)
self._check_consider_using_comprehension_constructor(node)
self._check_quit_exit_call(node)
@@ -1338,7 +1338,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"simplifiable-condition",
"condition-evals-to-constant",
)
- def visit_boolop(self, node):
+ def visit_boolop(self, node: nodes.BoolOp) -> None:
self._check_consider_merging_isinstance(node)
self._check_consider_using_in(node)
self._check_chained_comparison(node)
@@ -1527,7 +1527,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self.add_message("consider-using-join", node=aug_assign)
@utils.check_messages("consider-using-join")
- def visit_augassign(self, node):
+ def visit_augassign(self, node: nodes.AugAssign) -> None:
self._check_consider_using_join(node)
@utils.check_messages("unnecessary-comprehension", "unnecessary-dict-index-lookup")
@@ -1638,7 +1638,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
condition, true_value = node.values[0].values
return condition, true_value, false_value
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
self._return_nodes[node.name] = list(
node.nodes_of_class(nodes.Return, skip_klass=nodes.FunctionDef)
)
diff --git a/pylint/checkers/similar.py b/pylint/checkers/similar.py
index c3c4ed080..5a294e995 100644
--- a/pylint/checkers/similar.py
+++ b/pylint/checkers/similar.py
@@ -736,7 +736,7 @@ class SimilarChecker(BaseChecker, Similar, MapReduceMixin):
# for available dict keys/values see the optik parser 'add_option' method
options = (
(
- "min-similarity-lines", # type: ignore
+ "min-similarity-lines",
{
"default": DEFAULT_MIN_SIMILARITY_LINE,
"type": "int",
@@ -782,7 +782,7 @@ class SimilarChecker(BaseChecker, Similar, MapReduceMixin):
),
)
# reports
- reports = (("RP0801", "Duplication", report_similarities),) # type: ignore
+ reports = (("RP0801", "Duplication", report_similarities),)
def __init__(self, linter=None) -> None:
BaseChecker.__init__(self, linter)
diff --git a/pylint/checkers/spelling.py b/pylint/checkers/spelling.py
index d5ab5c1ca..3b2973ffa 100644
--- a/pylint/checkers/spelling.py
+++ b/pylint/checkers/spelling.py
@@ -33,6 +33,8 @@ import re
import tokenize
from typing import Pattern
+from astroid import nodes
+
from pylint.checkers import BaseTokenChecker
from pylint.checkers.utils import check_messages
from pylint.interfaces import IAstroidChecker, ITokenChecker
@@ -437,19 +439,19 @@ class SpellingChecker(BaseTokenChecker):
self._check_spelling("wrong-spelling-in-comment", token, start_row)
@check_messages("wrong-spelling-in-docstring")
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
if not self.initialized:
return
self._check_docstring(node)
@check_messages("wrong-spelling-in-docstring")
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
if not self.initialized:
return
self._check_docstring(node)
@check_messages("wrong-spelling-in-docstring")
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
if not self.initialized:
return
self._check_docstring(node)
diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py
index f11cbac98..ee5311b43 100644
--- a/pylint/checkers/stdlib.py
+++ b/pylint/checkers/stdlib.py
@@ -39,12 +39,14 @@
import sys
from collections.abc import Iterable
+from typing import Any, Dict, Set
import astroid
from astroid import nodes
from pylint.checkers import BaseChecker, DeprecatedMixin, utils
from pylint.interfaces import IAstroidChecker
+from pylint.lint import PyLinter
OPEN_FILES_MODE = ("open", "file")
OPEN_FILES_ENCODING = ("open", "read_text", "write_text")
@@ -117,7 +119,7 @@ DEPRECATED_DECORATORS = {
}
-DEPRECATED_METHODS = {
+DEPRECATED_METHODS: Dict = {
0: {
"cgi.parse_qs",
"cgi.parse_qsl",
@@ -444,9 +446,11 @@ class StdlibChecker(DeprecatedMixin, BaseChecker):
),
}
- def __init__(self, linter=None):
+ def __init__(
+ self, linter: PyLinter = None
+ ): # pylint: disable=super-init-not-called # See https://github.com/PyCQA/pylint/issues/4941
BaseChecker.__init__(self, linter)
- self._deprecated_methods = set()
+ self._deprecated_methods: Set[Any] = set()
self._deprecated_methods.update(DEPRECATED_METHODS[0])
for since_vers, func_list in DEPRECATED_METHODS[sys.version_info[0]].items():
if since_vers <= sys.version_info:
@@ -548,20 +552,20 @@ class StdlibChecker(DeprecatedMixin, BaseChecker):
self.check_deprecated_method(node, inferred)
@utils.check_messages("boolean-datetime")
- def visit_unaryop(self, node):
+ def visit_unaryop(self, node: nodes.UnaryOp) -> None:
if node.op == "not":
self._check_datetime(node.operand)
@utils.check_messages("boolean-datetime")
- def visit_if(self, node):
+ def visit_if(self, node: nodes.If) -> None:
self._check_datetime(node.test)
@utils.check_messages("boolean-datetime")
- def visit_ifexp(self, node):
+ def visit_ifexp(self, node: nodes.IfExp) -> None:
self._check_datetime(node.test)
@utils.check_messages("boolean-datetime")
- def visit_boolop(self, node):
+ def visit_boolop(self, node: nodes.BoolOp) -> None:
for value in node.values:
self._check_datetime(value)
diff --git a/pylint/checkers/strings.py b/pylint/checkers/strings.py
index b45b7bfdc..efdfdd9fe 100644
--- a/pylint/checkers/strings.py
+++ b/pylint/checkers/strings.py
@@ -278,7 +278,7 @@ class StringFormatChecker(BaseChecker):
"bad-string-format-type",
"format-string-without-interpolation",
)
- def visit_binop(self, node):
+ def visit_binop(self, node: nodes.BinOp) -> None:
if node.op != "%":
return
left = node.left
@@ -353,7 +353,8 @@ class StringFormatChecker(BaseChecker):
arg_type = utils.safe_infer(arg)
if (
format_type is not None
- and arg_type not in (None, astroid.Uninferable)
+ and arg_type
+ and arg_type != astroid.Uninferable
and not arg_matches_format_type(arg_type, format_type)
):
self.add_message(
@@ -373,11 +374,11 @@ class StringFormatChecker(BaseChecker):
# Check that the number of arguments passed to the RHS of
# the % operator matches the number required by the format
# string.
- args_elts = ()
+ args_elts = []
if isinstance(args, nodes.Tuple):
rhs_tuple = utils.safe_infer(args)
num_args = None
- if hasattr(rhs_tuple, "elts"):
+ if isinstance(rhs_tuple, nodes.BaseContainer):
args_elts = rhs_tuple.elts
num_args = len(args_elts)
elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
@@ -399,10 +400,7 @@ class StringFormatChecker(BaseChecker):
arg_type = utils.safe_infer(arg)
if (
arg_type
- not in (
- None,
- astroid.Uninferable,
- )
+ and arg_type != astroid.Uninferable
and not arg_matches_format_type(arg_type, format_type)
):
self.add_message(
@@ -412,7 +410,7 @@ class StringFormatChecker(BaseChecker):
)
@check_messages("f-string-without-interpolation")
- def visit_joinedstr(self, node):
+ def visit_joinedstr(self, node: nodes.JoinedStr) -> None:
if isinstance(node.parent, nodes.FormattedValue):
return
for value in node.values:
@@ -421,7 +419,7 @@ class StringFormatChecker(BaseChecker):
self.add_message("f-string-without-interpolation", node=node)
@check_messages(*MSGS)
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
func = utils.safe_infer(node.func)
if (
isinstance(func, astroid.BoundMethod)
@@ -750,18 +748,18 @@ class StringConstantChecker(BaseTokenChecker):
self.check_for_consistent_string_delimiters(tokens)
@check_messages("implicit-str-concat")
- def visit_list(self, node):
+ def visit_list(self, node: nodes.List) -> None:
self.check_for_concatenated_strings(node.elts, "list")
@check_messages("implicit-str-concat")
- def visit_set(self, node):
+ def visit_set(self, node: nodes.Set) -> None:
self.check_for_concatenated_strings(node.elts, "set")
@check_messages("implicit-str-concat")
- def visit_tuple(self, node):
+ def visit_tuple(self, node: nodes.Tuple) -> None:
self.check_for_concatenated_strings(node.elts, "tuple")
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
if isinstance(node.value, nodes.Const) and isinstance(node.value.value, str):
self.check_for_concatenated_strings([node.value], "assignment")
@@ -917,7 +915,7 @@ class StringConstantChecker(BaseTokenChecker):
@check_messages("redundant-u-string-prefix")
@check_messages("consider-using-f-string")
- def visit_const(self, node: nodes.Const):
+ def visit_const(self, node: nodes.Const) -> None:
if node.pytype() == "builtins.str" and not isinstance(
node.parent, nodes.JoinedStr
):
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index a79d2fa6b..aeab4645e 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -67,7 +67,7 @@ import types
from collections import deque
from collections.abc import Sequence
from functools import singledispatch
-from typing import Pattern, Tuple
+from typing import Any, Callable, Iterator, List, Optional, Pattern, Tuple
import astroid
from astroid import bases, nodes
@@ -915,7 +915,7 @@ accessed. Python regular expressions are accepted.",
return tuple(re.compile(exp) for exp in generated_members)
@check_messages("keyword-arg-before-vararg")
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
# check for keyword arg before varargs
if node.args.vararg and node.args.defaults:
self.add_message("keyword-arg-before-vararg", node=node, args=(node.name))
@@ -923,7 +923,7 @@ accessed. Python regular expressions are accepted.",
visit_asyncfunctiondef = visit_functiondef
@check_messages("invalid-metaclass")
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
def _metaclass_name(metaclass):
# pylint: disable=unidiomatic-typecheck
if isinstance(metaclass, (nodes.ClassDef, nodes.FunctionDef)):
@@ -955,15 +955,15 @@ accessed. Python regular expressions are accepted.",
"invalid-metaclass", node=node, args=(_metaclass_name(metaclass),)
)
- def visit_assignattr(self, node):
+ def visit_assignattr(self, node: nodes.AssignAttr) -> None:
if isinstance(node.assign_type(), nodes.AugAssign):
self.visit_attribute(node)
- def visit_delattr(self, node):
+ def visit_delattr(self, node: nodes.DelAttr) -> None:
self.visit_attribute(node)
@check_messages("no-member", "c-extension-no-member")
- def visit_attribute(self, node):
+ def visit_attribute(self, node: nodes.Attribute) -> None:
"""check that the accessed attribute exists
to avoid too much false positives for now, we'll consider the code as
@@ -1090,7 +1090,7 @@ accessed. Python regular expressions are accepted.",
"assignment-from-none",
"non-str-assignment-to-dunder-name",
)
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
"""
Process assignments in the AST.
"""
@@ -1270,7 +1270,7 @@ accessed. Python regular expressions are accepted.",
# pylint: disable=too-many-branches,too-many-locals
@check_messages(*(list(MSGS.keys())))
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
"""check that called functions/methods are inferred to callable objects,
and that the arguments passed to the function match the parameters in
the inferred function's definition
@@ -1359,7 +1359,7 @@ accessed. Python regular expressions are accepted.",
# Analyze the list of formal parameters.
args = list(itertools.chain(called.args.posonlyargs or (), called.args.args))
num_mandatory_parameters = len(args) - len(called.args.defaults)
- parameters = []
+ parameters: List[List[Any]] = []
parameter_name_to_index = {}
for i, arg in enumerate(args):
if isinstance(arg, nodes.Tuple):
@@ -1553,7 +1553,7 @@ accessed. Python regular expressions are accepted.",
return None
@check_messages("invalid-sequence-index")
- def visit_extslice(self, node):
+ def visit_extslice(self, node: nodes.ExtSlice) -> None:
if not node.parent or not hasattr(node.parent, "value"):
return None
# Check extended slice objects as if they were used as a sequence
@@ -1615,7 +1615,7 @@ accessed. Python regular expressions are accepted.",
self.add_message("invalid-slice-index", node=node)
@check_messages("not-context-manager")
- def visit_with(self, node):
+ def visit_with(self, node: nodes.With) -> None:
for ctx_mgr, _ in node.items:
context = astroid.context.InferenceContext()
inferred = safe_infer(ctx_mgr, context=context)
@@ -1641,7 +1641,9 @@ accessed. Python regular expressions are accepted.",
# of self explaining tests.
# Retrieve node from all previusly visited nodes in the the inference history
- context_path_names = filter(None, _unflatten(context.path))
+ context_path_names: Iterator[Any] = filter(
+ None, _unflatten(context.path)
+ )
inferred_paths = _flatten_container(
safe_infer(path) for path in context_path_names
)
@@ -1677,7 +1679,7 @@ accessed. Python regular expressions are accepted.",
)
@check_messages("invalid-unary-operand-type")
- def visit_unaryop(self, node):
+ def visit_unaryop(self, node: nodes.UnaryOp) -> None:
"""Detect TypeErrors for unary operands."""
for error in node.type_errors():
@@ -1685,7 +1687,7 @@ accessed. Python regular expressions are accepted.",
self.add_message("invalid-unary-operand-type", args=str(error), node=node)
@check_messages("unsupported-binary-operation")
- def visit_binop(self, node: nodes.BinOp):
+ def visit_binop(self, node: nodes.BinOp) -> None:
if node.op == "|":
self._detect_unsupported_alternative_union_syntax(node)
@@ -1740,12 +1742,12 @@ accessed. Python regular expressions are accepted.",
break
@check_messages("unsupported-binary-operation")
- def _visit_binop(self, node):
+ def _visit_binop(self, node: nodes.BinOp) -> None:
"""Detect TypeErrors for binary arithmetic operands."""
self._check_binop_errors(node)
@check_messages("unsupported-binary-operation")
- def _visit_augassign(self, node):
+ def _visit_augassign(self, node: nodes.AugAssign) -> None:
"""Detect TypeErrors for augmented binary arithmetic operands."""
self._check_binop_errors(node)
@@ -1773,7 +1775,7 @@ accessed. Python regular expressions are accepted.",
)
@check_messages("unsupported-membership-test")
- def visit_compare(self, node):
+ def visit_compare(self, node: nodes.Compare) -> None:
if len(node.ops) != 1:
return
@@ -1789,17 +1791,17 @@ accessed. Python regular expressions are accepted.",
"invalid-sequence-index",
"invalid-slice-index",
)
- def visit_subscript(self, node):
+ def visit_subscript(self, node: nodes.Subscript) -> None:
self._check_invalid_sequence_index(node)
- supported_protocol = None
+ supported_protocol: Optional[Callable[[Any, Any], bool]] = None
if isinstance(node.value, (nodes.ListComp, nodes.DictComp)):
return
if isinstance(node.value, nodes.Dict):
# Assert dict key is hashable
inferred = safe_infer(node.slice)
- if inferred not in (None, astroid.Uninferable):
+ if inferred and inferred != astroid.Uninferable:
try:
hash_fn = next(inferred.igetattr("__hash__"))
except astroid.InferenceError:
@@ -1838,11 +1840,11 @@ accessed. Python regular expressions are accepted.",
return # It would be better to handle function
# decorators, but let's start slow.
- if not supported_protocol(inferred, node):
+ if supported_protocol and not supported_protocol(inferred, node):
self.add_message(msg, args=node.value.as_string(), node=node.value)
@check_messages("dict-items-missing-iter")
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
if not isinstance(node.target, nodes.Tuple):
# target is not a tuple
return
@@ -1939,43 +1941,43 @@ class IterableChecker(BaseChecker):
self.add_message("not-a-mapping", args=node.as_string(), node=node)
@check_messages("not-an-iterable")
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
self._check_iterable(node.iter)
@check_messages("not-an-iterable")
- def visit_asyncfor(self, node):
+ def visit_asyncfor(self, node: nodes.AsyncFor) -> None:
self._check_iterable(node.iter, check_async=True)
@check_messages("not-an-iterable")
- def visit_yieldfrom(self, node):
+ def visit_yieldfrom(self, node: nodes.YieldFrom) -> None:
if self._is_asyncio_coroutine(node.value):
return
self._check_iterable(node.value)
@check_messages("not-an-iterable", "not-a-mapping")
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
for stararg in node.starargs:
self._check_iterable(stararg.value)
for kwarg in node.kwargs:
self._check_mapping(kwarg.value)
@check_messages("not-an-iterable")
- def visit_listcomp(self, node):
+ def visit_listcomp(self, node: nodes.ListComp) -> None:
for gen in node.generators:
self._check_iterable(gen.iter, check_async=gen.is_async)
@check_messages("not-an-iterable")
- def visit_dictcomp(self, node):
+ def visit_dictcomp(self, node: nodes.DictComp) -> None:
for gen in node.generators:
self._check_iterable(gen.iter, check_async=gen.is_async)
@check_messages("not-an-iterable")
- def visit_setcomp(self, node):
+ def visit_setcomp(self, node: nodes.SetComp) -> None:
for gen in node.generators:
self._check_iterable(gen.iter, check_async=gen.is_async)
@check_messages("not-an-iterable")
- def visit_generatorexp(self, node):
+ def visit_generatorexp(self, node: nodes.GeneratorExp) -> None:
for gen in node.generators:
self._check_iterable(gen.iter, check_async=gen.is_async)
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index 05f69401c..6c08a48b4 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -60,18 +60,7 @@ import numbers
import re
import string
from functools import lru_cache, partial
-from typing import (
- Any,
- Callable,
- Dict,
- Iterable,
- List,
- Match,
- Optional,
- Set,
- Tuple,
- Union,
-)
+from typing import Callable, Dict, Iterable, List, Match, Optional, Set, Tuple, Union
import _string
import astroid
@@ -228,7 +217,7 @@ _SPECIAL_METHODS_PARAMS = {
SPECIAL_METHODS_PARAMS = {
name: params
for params, methods in _SPECIAL_METHODS_PARAMS.items()
- for name in methods # type: ignore
+ for name in methods
}
PYMETHODS = set(SPECIAL_METHODS_PARAMS)
@@ -748,8 +737,8 @@ def error_of_type(handler: nodes.ExceptHandler, error_type) -> bool:
return error
if not isinstance(error_type, tuple):
- error_type = (error_type,) # type: ignore
- expected_errors = {stringify_error(error) for error in error_type} # type: ignore
+ error_type = (error_type,)
+ expected_errors = {stringify_error(error) for error in error_type}
if not handler.type:
return False
return handler.catch(expected_errors)
@@ -1164,11 +1153,11 @@ def supports_getitem(value: nodes.NodeNG, node: nodes.NodeNG) -> bool:
return _supports_protocol(value, _supports_getitem_protocol)
-def supports_setitem(value: nodes.NodeNG, *_: Any) -> bool:
+def supports_setitem(value: nodes.NodeNG, _: nodes.NodeNG) -> bool:
return _supports_protocol(value, _supports_setitem_protocol)
-def supports_delitem(value: nodes.NodeNG, *_: Any) -> bool:
+def supports_delitem(value: nodes.NodeNG, _: nodes.NodeNG) -> bool:
return _supports_protocol(value, _supports_delitem_protocol)
@@ -1245,7 +1234,7 @@ def is_none(node: nodes.NodeNG) -> bool:
)
-def node_type(node: nodes.NodeNG) -> Optional[type]:
+def node_type(node: nodes.NodeNG) -> Optional[nodes.NodeNG]:
"""Return the inferred type for `node`
If there is more than one possible type, or if inferred type is Uninferable or None,
@@ -1253,7 +1242,7 @@ def node_type(node: nodes.NodeNG) -> Optional[type]:
"""
# check there is only one possible type for the assign node. Else we
# don't handle it for now
- types = set()
+ types: Set[nodes.NodeNG] = set()
try:
for var_type in node.infer():
if var_type == astroid.Uninferable or is_none(var_type):
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 922cc0370..aa5ac14a1 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -715,7 +715,7 @@ class VariablesChecker(BaseChecker):
self._postponed_evaluation_enabled = False
@utils.check_messages("redefined-outer-name")
- def visit_for(self, node):
+ def visit_for(self, node: nodes.For) -> None:
assigned_to = [a.name for a in node.target.nodes_of_class(nodes.AssignName)]
# Only check variables that are used
@@ -737,11 +737,11 @@ class VariablesChecker(BaseChecker):
self._loop_variables.append((node, assigned_to))
@utils.check_messages("redefined-outer-name")
- def leave_for(self, node):
+ def leave_for(self, node: nodes.For) -> None:
self._loop_variables.pop()
self._store_type_annotation_names(node)
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
"""visit module : update consumption analysis variable
checks globals doesn't overrides builtins
"""
@@ -763,7 +763,7 @@ class VariablesChecker(BaseChecker):
"invalid-all-format",
"unused-variable",
)
- def leave_module(self, node):
+ def leave_module(self, node: nodes.Module) -> None:
"""leave module: check globals"""
assert len(self._to_consume) == 1
@@ -782,52 +782,52 @@ class VariablesChecker(BaseChecker):
self._check_imports(not_consumed)
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
"""visit class: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "class"))
- def leave_classdef(self, _):
+ def leave_classdef(self, _: nodes.ClassDef) -> None:
"""leave class: update consumption analysis variable"""
# do not check for not used locals here (no sense)
self._to_consume.pop()
- def visit_lambda(self, node):
+ def visit_lambda(self, node: nodes.Lambda) -> None:
"""visit lambda: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "lambda"))
- def leave_lambda(self, _):
+ def leave_lambda(self, _: nodes.Lambda) -> None:
"""leave lambda: update consumption analysis variable"""
# do not check for not used locals here
self._to_consume.pop()
- def visit_generatorexp(self, node):
+ def visit_generatorexp(self, node: nodes.GeneratorExp) -> None:
"""visit genexpr: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "comprehension"))
- def leave_generatorexp(self, _):
+ def leave_generatorexp(self, _: nodes.GeneratorExp) -> None:
"""leave genexpr: update consumption analysis variable"""
# do not check for not used locals here
self._to_consume.pop()
- def visit_dictcomp(self, node):
+ def visit_dictcomp(self, node: nodes.DictComp) -> None:
"""visit dictcomp: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "comprehension"))
- def leave_dictcomp(self, _):
+ def leave_dictcomp(self, _: nodes.DictComp) -> None:
"""leave dictcomp: update consumption analysis variable"""
# do not check for not used locals here
self._to_consume.pop()
- def visit_setcomp(self, node):
+ def visit_setcomp(self, node: nodes.SetComp) -> None:
"""visit setcomp: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "comprehension"))
- def leave_setcomp(self, _):
+ def leave_setcomp(self, _: nodes.SetComp) -> None:
"""leave setcomp: update consumption analysis variable"""
# do not check for not used locals here
self._to_consume.pop()
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""visit function: update consumption analysis variable and check locals"""
self._to_consume.append(NamesConsumer(node, "function"))
if not (
@@ -869,7 +869,7 @@ class VariablesChecker(BaseChecker):
# do not print Redefining builtin for additional builtins
self.add_message("redefined-builtin", args=name, node=stmt)
- def leave_functiondef(self, node):
+ def leave_functiondef(self, node: nodes.FunctionDef) -> None:
"""leave function: check function's locals are consumed"""
self._check_metaclasses(node)
@@ -911,7 +911,7 @@ class VariablesChecker(BaseChecker):
"global-at-module-level",
"redefined-builtin",
)
- def visit_global(self, node):
+ def visit_global(self, node: nodes.Global) -> None:
"""check names imported exists in the global scope"""
frame = node.frame()
if isinstance(frame, nodes.Module):
@@ -955,15 +955,15 @@ class VariablesChecker(BaseChecker):
if default_message:
self.add_message("global-statement", node=node)
- def visit_assignname(self, node):
+ def visit_assignname(self, node: nodes.AssignName) -> None:
if isinstance(node.assign_type(), nodes.AugAssign):
self.visit_name(node)
- def visit_delname(self, node):
+ def visit_delname(self, node: nodes.DelName) -> None:
self.visit_name(node)
# pylint: disable=too-many-branches
- def visit_name(self, node):
+ def visit_name(self, node: nodes.Name) -> None:
"""Check that a name is defined in the current scope"""
stmt = node.statement()
if stmt.fromlineno is None:
@@ -1249,7 +1249,7 @@ class VariablesChecker(BaseChecker):
@utils.check_messages(
"unbalanced-tuple-unpacking", "unpacking-non-sequence", "self-cls-assignment"
)
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
"""Check unbalanced tuple unpacking for assignments
and unpacking non-sequences as well as in case self/cls
get assigned.
@@ -1267,22 +1267,22 @@ class VariablesChecker(BaseChecker):
return
# listcomp have now also their scope
- def visit_listcomp(self, node):
+ def visit_listcomp(self, node: nodes.ListComp) -> None:
"""visit dictcomp: update consumption analysis variable"""
self._to_consume.append(NamesConsumer(node, "comprehension"))
- def leave_listcomp(self, _):
+ def leave_listcomp(self, _: nodes.ListComp) -> None:
"""leave dictcomp: update consumption analysis variable"""
# do not check for not used locals here
self._to_consume.pop()
- def leave_assign(self, node):
+ def leave_assign(self, node: nodes.Assign) -> None:
self._store_type_annotation_names(node)
- def leave_with(self, node):
+ def leave_with(self, node: nodes.With) -> None:
self._store_type_annotation_names(node)
- def visit_arguments(self, node):
+ def visit_arguments(self, node: nodes.Arguments) -> None:
for annotation in node.type_comment_args:
self._store_type_annotation_node(annotation)
diff --git a/pylint/extensions/bad_builtin.py b/pylint/extensions/bad_builtin.py
index ad5d3120a..55908e293 100644
--- a/pylint/extensions/bad_builtin.py
+++ b/pylint/extensions/bad_builtin.py
@@ -51,7 +51,7 @@ class BadBuiltinChecker(BaseChecker):
)
@check_messages("bad-builtin")
- def visit_call(self, node):
+ def visit_call(self, node: nodes.Call) -> None:
if isinstance(node.func, nodes.Name):
name = node.func.name
# ignore the name if it's not a builtin (i.e. not defined in the
diff --git a/pylint/extensions/broad_try_clause.py b/pylint/extensions/broad_try_clause.py
index b7d2fc974..5cc894af4 100644
--- a/pylint/extensions/broad_try_clause.py
+++ b/pylint/extensions/broad_try_clause.py
@@ -10,7 +10,7 @@
"""Looks for try/except statements with too much code in the try clause."""
-from astroid.node_classes import For, If, While, With
+from astroid import nodes
from pylint import checkers, interfaces
@@ -53,12 +53,12 @@ class BroadTryClauseChecker(checkers.BaseChecker):
statement_count = len(try_node.body)
for body_node in try_node.body:
- if isinstance(body_node, (For, If, While, With)):
+ if isinstance(body_node, (nodes.For, nodes.If, nodes.While, nodes.With)):
statement_count += self._count_statements(body_node)
return statement_count
- def visit_tryexcept(self, node):
+ def visit_tryexcept(self, node: nodes.TryExcept) -> None:
try_clause_statements = self._count_statements(node)
if try_clause_statements > self.config.max_try_statements:
msg = f"try clause contains {try_clause_statements} statements, expected at most {self.config.max_try_statements}"
@@ -66,7 +66,7 @@ class BroadTryClauseChecker(checkers.BaseChecker):
"too-many-try-statements", node.lineno, node=node, args=msg
)
- def visit_tryfinally(self, node):
+ def visit_tryfinally(self, node: nodes.TryFinally) -> None:
self.visit_tryexcept(node)
diff --git a/pylint/extensions/check_elif.py b/pylint/extensions/check_elif.py
index d0f487dd1..bed840fb6 100644
--- a/pylint/extensions/check_elif.py
+++ b/pylint/extensions/check_elif.py
@@ -48,19 +48,19 @@ class ElseifUsedChecker(BaseTokenChecker):
elif token == "if":
self._elifs.append(False)
- def leave_module(self, _):
+ def leave_module(self, _: nodes.Module) -> None:
self._init()
- def visit_ifexp(self, node):
+ def visit_ifexp(self, node: nodes.IfExp) -> None:
if isinstance(node.parent, nodes.FormattedValue):
return
self._if_counter += 1
- def visit_comprehension(self, node):
+ def visit_comprehension(self, node: nodes.Comprehension) -> None:
self._if_counter += len(node.ifs)
@check_messages("else-if-used")
- def visit_if(self, node):
+ def visit_if(self, node: nodes.If) -> None:
if isinstance(node.parent, nodes.If):
orelse = node.parent.orelse
# current if node must directly follow an "else"
diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py
index 0d8bfd164..8ec8d4a6a 100644
--- a/pylint/extensions/code_style.py
+++ b/pylint/extensions/code_style.py
@@ -77,9 +77,9 @@ class CodeStyleChecker(BaseChecker):
super().__init__(linter=linter)
def open(self) -> None:
- py_version: Tuple[int, int] = get_global_option(self, "py-version") # type: ignore
+ py_version: Tuple[int, int] = get_global_option(self, "py-version")
self._py38_plus = py_version >= (3, 8)
- self._max_length: int = ( # type: ignore
+ self._max_length: int = (
self.config.max_line_length_suggestions
or get_global_option(self, "max-line-length")
)
@@ -160,7 +160,7 @@ class CodeStyleChecker(BaseChecker):
for _, dict_value in node.items
):
# Make sure all sublists have the same length > 0
- list_length = len(node.items[0][1].elts) # type: ignore
+ list_length = len(node.items[0][1].elts)
if list_length == 0:
return
for _, dict_value in node.items[1:]:
diff --git a/pylint/extensions/comparetozero.py b/pylint/extensions/comparetozero.py
index 04a3f2942..05020bf67 100644
--- a/pylint/extensions/comparetozero.py
+++ b/pylint/extensions/comparetozero.py
@@ -12,8 +12,10 @@
"""Looks for comparisons to zero."""
import itertools
+from typing import Any, Iterable
import astroid
+from astroid import nodes
from pylint import checkers, interfaces
from pylint.checkers import utils
@@ -46,7 +48,7 @@ class CompareToZeroChecker(checkers.BaseChecker):
options = ()
@utils.check_messages("compare-to-zero")
- def visit_compare(self, node):
+ def visit_compare(self, node: nodes.Compare) -> None:
_operators = ["!=", "==", "is not", "is"]
# note: astroid.Compare has the left most operand in node.left
# while the rest are a list of tuples in node.ops
@@ -54,7 +56,8 @@ class CompareToZeroChecker(checkers.BaseChecker):
# here we squash everything into `ops` to make it easier for processing later
ops = [("", node.left)]
ops.extend(node.ops)
- ops = list(itertools.chain(*ops))
+ iter_ops: Iterable[Any] = iter(ops)
+ ops = list(itertools.chain(*iter_ops))
for ops_idx in range(len(ops) - 2):
op_1 = ops[ops_idx]
diff --git a/pylint/extensions/confusing_elif.py b/pylint/extensions/confusing_elif.py
index ba1e6ff01..2b62bc02c 100644
--- a/pylint/extensions/confusing_elif.py
+++ b/pylint/extensions/confusing_elif.py
@@ -32,7 +32,7 @@ class ConfusingConsecutiveElifChecker(BaseChecker):
}
@check_messages("confusing-consecutive-elif")
- def visit_if(self, node: nodes.If):
+ def visit_if(self, node: nodes.If) -> None:
body_ends_with_if = isinstance(
node.body[-1], nodes.If
) and self._has_no_else_clause(node.body[-1])
diff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py
index 4344444ff..bb5ac6805 100644
--- a/pylint/extensions/docparams.py
+++ b/pylint/extensions/docparams.py
@@ -27,6 +27,7 @@ import re
from typing import Optional
import astroid
+from astroid import nodes
from pylint.checkers import BaseChecker
from pylint.checkers import utils as checker_utils
@@ -205,7 +206,7 @@ class DocstringParameterChecker(BaseChecker):
constructor_names = {"__init__", "__new__"}
not_needed_param_in_docstring = {"self", "cls"}
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""Called for function and method definitions (def).
:param node: Node for a function or method definition in the AST
@@ -278,7 +279,7 @@ class DocstringParameterChecker(BaseChecker):
) and not node.is_generator():
self.add_message("redundant-yields-doc", node=node)
- def visit_raise(self, node):
+ def visit_raise(self, node: nodes.Raise) -> None:
func_node = node.frame()
if not isinstance(func_node, astroid.FunctionDef):
return
@@ -308,7 +309,7 @@ class DocstringParameterChecker(BaseChecker):
missing_excs = expected_excs - found_excs_class_names
self._add_raise_message(missing_excs, func_node)
- def visit_return(self, node):
+ def visit_return(self, node: nodes.Return) -> None:
if not utils.returns_something(node):
return
@@ -331,7 +332,7 @@ class DocstringParameterChecker(BaseChecker):
if not (doc.has_rtype() or (doc.has_property_type() and is_property)):
self.add_message("missing-return-type-doc", node=func_node)
- def visit_yield(self, node):
+ def visit_yield(self, node: nodes.Yield) -> None:
func_node = node.frame()
if not isinstance(func_node, astroid.FunctionDef):
return
@@ -353,7 +354,7 @@ class DocstringParameterChecker(BaseChecker):
if not (doc_has_yields_type or func_node.returns):
self.add_message("missing-yield-type-doc", node=func_node)
- def visit_yieldfrom(self, node):
+ def visit_yieldfrom(self, node: nodes.YieldFrom) -> None:
self.visit_yield(node)
def _compare_missing_args(
@@ -612,7 +613,7 @@ class DocstringParameterChecker(BaseChecker):
:type missing_excs: set(str)
:param node: The node show the message on.
- :type node: astroid.node_classes.NodeNG
+ :type node: nodes.NodeNG
"""
if node.is_abstract():
try:
diff --git a/pylint/extensions/docstyle.py b/pylint/extensions/docstyle.py
index e56c707bf..816bda2e2 100644
--- a/pylint/extensions/docstyle.py
+++ b/pylint/extensions/docstyle.py
@@ -11,6 +11,8 @@
import linecache
+from astroid import nodes
+
from pylint import checkers
from pylint.checkers.utils import check_messages
from pylint.interfaces import HIGH, IAstroidChecker
@@ -36,13 +38,13 @@ class DocStringStyleChecker(checkers.BaseChecker):
}
@check_messages("docstring-first-line-empty", "bad-docstring-quotes")
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
self._check_docstring("module", node)
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
self._check_docstring("class", node)
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
ftype = "method" if node.is_method() else "function"
self._check_docstring(ftype, node)
diff --git a/pylint/extensions/emptystring.py b/pylint/extensions/emptystring.py
index 6f07a8e81..f5a4a2740 100644
--- a/pylint/extensions/emptystring.py
+++ b/pylint/extensions/emptystring.py
@@ -11,6 +11,7 @@
"""Looks for comparisons to empty string."""
import itertools
+from typing import Any, Iterable
from astroid import nodes
@@ -45,7 +46,7 @@ class CompareToEmptyStringChecker(checkers.BaseChecker):
options = ()
@utils.check_messages("compare-to-empty-string")
- def visit_compare(self, node):
+ def visit_compare(self, node: nodes.Compare) -> None:
_operators = ["!=", "==", "is not", "is"]
# note: astroid.Compare has the left most operand in node.left
# while the rest are a list of tuples in node.ops
@@ -53,7 +54,8 @@ class CompareToEmptyStringChecker(checkers.BaseChecker):
# here we squash everything into `ops` to make it easier for processing later
ops = [("", node.left)]
ops.extend(node.ops)
- ops = list(itertools.chain(*ops))
+ iter_ops: Iterable[Any] = iter(ops)
+ ops = list(itertools.chain(*iter_ops))
for ops_idx in range(len(ops) - 2):
op_1 = ops[ops_idx]
diff --git a/pylint/extensions/mccabe.py b/pylint/extensions/mccabe.py
index c85588ca2..86b8eb943 100644
--- a/pylint/extensions/mccabe.py
+++ b/pylint/extensions/mccabe.py
@@ -11,6 +11,7 @@
"""Module to add McCabe checker class for pylint. """
+from astroid import nodes
from mccabe import PathGraph as Mccabe_PathGraph
from mccabe import PathGraphingAstVisitor as Mccabe_PathGraphingAstVisitor
@@ -171,7 +172,7 @@ class McCabeMethodChecker(checkers.BaseChecker):
)
@check_messages("too-complex")
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
"""visit an astroid.Module node to check too complex rating and
add message if is greather than max_complexity stored from options"""
visitor = PathGraphingAstVisitor()
diff --git a/pylint/extensions/overlapping_exceptions.py b/pylint/extensions/overlapping_exceptions.py
index 891dde59f..2ed9038e3 100644
--- a/pylint/extensions/overlapping_exceptions.py
+++ b/pylint/extensions/overlapping_exceptions.py
@@ -3,7 +3,10 @@
"""Looks for overlapping exceptions."""
+from typing import Any, List, Tuple
+
import astroid
+from astroid import nodes
from pylint import checkers, interfaces
from pylint.checkers import utils
@@ -29,7 +32,7 @@ class OverlappingExceptionsChecker(checkers.BaseChecker):
options = ()
@utils.check_messages("overlapping-except")
- def visit_tryexcept(self, node):
+ def visit_tryexcept(self, node: nodes.TryExcept) -> None:
"""check for empty except"""
for handler in node.handlers:
if handler.type is None:
@@ -41,7 +44,7 @@ class OverlappingExceptionsChecker(checkers.BaseChecker):
except astroid.InferenceError:
continue
- handled_in_clause = []
+ handled_in_clause: List[Tuple[Any, Any]] = []
for part, exc in excs:
if exc is astroid.Uninferable:
continue
diff --git a/pylint/extensions/redefined_variable_type.py b/pylint/extensions/redefined_variable_type.py
index b634bb6c9..26dc3ecc2 100644
--- a/pylint/extensions/redefined_variable_type.py
+++ b/pylint/extensions/redefined_variable_type.py
@@ -10,6 +10,8 @@
# 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
+from typing import List
+
from astroid import nodes
from pylint.checkers import BaseChecker
@@ -43,18 +45,18 @@ class MultipleTypesChecker(BaseChecker):
)
}
- def visit_classdef(self, _):
+ def visit_classdef(self, _: nodes.ClassDef) -> None:
self._assigns.append({})
@check_messages("redefined-variable-type")
- def leave_classdef(self, _):
+ def leave_classdef(self, _: nodes.ClassDef) -> None:
self._check_and_add_messages()
visit_functiondef = visit_classdef
leave_functiondef = leave_module = leave_classdef
- def visit_module(self, _):
- self._assigns = [{}]
+ def visit_module(self, _: nodes.Module) -> None:
+ self._assigns: List[dict] = [{}]
def _check_and_add_messages(self):
assigns = self._assigns.pop()
@@ -93,7 +95,7 @@ class MultipleTypesChecker(BaseChecker):
)
break
- def visit_assign(self, node):
+ def visit_assign(self, node: nodes.Assign) -> None:
# we don't handle multiple assignment nor slice assignment
target = node.targets[0]
if isinstance(target, (nodes.Tuple, nodes.Subscript)):
diff --git a/pylint/extensions/typing.py b/pylint/extensions/typing.py
index cf0281f33..66e46bcfd 100644
--- a/pylint/extensions/typing.py
+++ b/pylint/extensions/typing.py
@@ -139,7 +139,7 @@ class TypingChecker(BaseChecker):
self._consider_using_alias_msgs: List[DeprecatedTypingAliasMsg] = []
def open(self) -> None:
- py_version: Tuple[int, int] = get_global_option(self, "py-version") # type: ignore
+ py_version: Tuple[int, int] = get_global_option(self, "py-version")
self._py37_plus = py_version >= (3, 7)
self._py39_plus = py_version >= (3, 9)
self._py310_plus = py_version >= (3, 10)
@@ -173,7 +173,7 @@ class TypingChecker(BaseChecker):
"consider-using-alias",
"consider-alternative-union-syntax",
)
- def visit_attribute(self, node: nodes.Attribute):
+ def visit_attribute(self, node: nodes.Attribute) -> None:
if self._should_check_typing_alias and node.attrname in ALIAS_NAMES:
self._check_for_typing_alias(node)
if self._should_check_alternative_union_syntax and node.attrname in UNION_NAMES:
diff --git a/pylint/extensions/while_used.py b/pylint/extensions/while_used.py
index 9476478c3..8d05ace90 100644
--- a/pylint/extensions/while_used.py
+++ b/pylint/extensions/while_used.py
@@ -1,4 +1,6 @@
"""Check for use of while loops."""
+from astroid import nodes
+
from pylint.checkers import BaseChecker
from pylint.checkers.utils import check_messages
from pylint.interfaces import IAstroidChecker
@@ -17,7 +19,7 @@ class WhileChecker(BaseChecker):
}
@check_messages("while-used")
- def visit_while(self, node):
+ def visit_while(self, node: nodes.While) -> None:
self.add_message("while-used", node=node)
diff --git a/pylint/graph.py b/pylint/graph.py
index 927fac47e..a5e336226 100644
--- a/pylint/graph.py
+++ b/pylint/graph.py
@@ -109,8 +109,8 @@ class DotBackend:
os.close(pdot)
else:
dot_sourcepath = outputfile
- with codecs.open(dot_sourcepath, "w", encoding="utf8") as pdot: # type: ignore
- pdot.write(self.source) # type: ignore
+ with codecs.open(dot_sourcepath, "w", encoding="utf8") as file:
+ file.write(self.source)
if target not in graphviz_extensions:
if shutil.which(self.renderer) is None:
raise RuntimeError(
diff --git a/pylint/message/message_id_store.py b/pylint/message/message_id_store.py
index 2f061e4b6..84c3747fe 100644
--- a/pylint/message/message_id_store.py
+++ b/pylint/message/message_id_store.py
@@ -76,9 +76,9 @@ class MessageIdStore:
if existing_msgid is not None:
if existing_msgid != msgid:
self._raise_duplicate_msgid(symbol, msgid, existing_msgid)
- if existing_symbol != symbol:
+ if existing_symbol and existing_symbol != symbol:
# See https://github.com/python/mypy/issues/10559
- self._raise_duplicate_symbol(msgid, symbol, existing_symbol) # type: ignore
+ self._raise_duplicate_symbol(msgid, symbol, existing_symbol)
@staticmethod
def _raise_duplicate_symbol(msgid: str, symbol: str, other_symbol: str):
@@ -105,11 +105,12 @@ class MessageIdStore:
"""Return msgids but the input can be a symbol."""
# Only msgid can have a digit as second letter
is_msgid: bool = msgid_or_symbol[1:].isdigit()
+ msgid = None
if is_msgid:
msgid = msgid_or_symbol.upper()
symbol = self.__msgid_to_symbol.get(msgid)
else:
- msgid = self.__symbol_to_msgid.get(msgid_or_symbol) # type: ignore
+ msgid = self.__symbol_to_msgid.get(msgid_or_symbol)
symbol = msgid_or_symbol
if msgid is None or symbol is None or not msgid or not symbol:
error_msg = f"No such message id or symbol '{msgid_or_symbol}'."
diff --git a/pylint/pyreverse/diadefslib.py b/pylint/pyreverse/diadefslib.py
index df9a7f6ad..776b83218 100644
--- a/pylint/pyreverse/diadefslib.py
+++ b/pylint/pyreverse/diadefslib.py
@@ -20,10 +20,13 @@
"""handle diagram generation options for class diagram or default diagrams
"""
+from typing import Any, Optional
+
import astroid
from astroid import nodes
from pylint.pyreverse.diagrams import ClassDiagram, PackageDiagram
+from pylint.pyreverse.inspector import Project
from pylint.pyreverse.utils import LocalsVisitor
# diagram generators ##########################################################
@@ -132,19 +135,21 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator):
DiaDefGenerator.__init__(self, linker, handler)
LocalsVisitor.__init__(self)
- def visit_project(self, node):
+ def visit_project(self, node: Project) -> None:
"""visit a pyreverse.utils.Project node
create a diagram definition for packages
"""
mode = self.config.mode
if len(node.modules) > 1:
- self.pkgdiagram = PackageDiagram(f"packages {node.name}", mode)
+ self.pkgdiagram: Optional[PackageDiagram] = PackageDiagram(
+ f"packages {node.name}", mode
+ )
else:
self.pkgdiagram = None
self.classdiagram = ClassDiagram(f"classes {node.name}", mode)
- def leave_project(self, node): # pylint: disable=unused-argument
+ def leave_project(self, _: Project) -> Any:
"""leave the pyreverse.utils.Project node
return the generated diagram definition
@@ -153,7 +158,7 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator):
return self.pkgdiagram, self.classdiagram
return (self.classdiagram,)
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
"""visit an astroid.Module node
add this class to the package diagram definition
@@ -162,7 +167,7 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator):
self.linker.visit(node)
self.pkgdiagram.add_object(node.name, node)
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
"""visit an astroid.Class node
add this class to the class diagram definition
@@ -170,7 +175,7 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator):
anc_level, association_level = self._get_levels()
self.extract_classes(node, anc_level, association_level)
- def visit_importfrom(self, node):
+ def visit_importfrom(self, node: nodes.ImportFrom) -> None:
"""visit astroid.ImportFrom and catch modules for package diagram"""
if self.pkgdiagram:
self.pkgdiagram.add_from_depend(node, node.modname)
diff --git a/pylint/pyreverse/inspector.py b/pylint/pyreverse/inspector.py
index 6471b2b61..0b4773153 100644
--- a/pylint/pyreverse/inspector.py
+++ b/pylint/pyreverse/inspector.py
@@ -53,7 +53,7 @@ def interfaces(node, herited=True, handler_func=_iface_hdlr):
return
found = set()
missing = False
- for iface in astroid.node_classes.unpack_infer(implements):
+ for iface in nodes.unpack_infer(implements):
if iface is astroid.Uninferable:
missing = True
continue
@@ -80,6 +80,35 @@ class IdGeneratorMixIn:
return self.id_count
+class Project:
+ """a project handle a set of modules / packages"""
+
+ def __init__(self, name=""):
+ self.name = name
+ self.uid = None
+ self.path = None
+ self.modules = []
+ self.locals = {}
+ self.__getitem__ = self.locals.__getitem__
+ self.__iter__ = self.locals.__iter__
+ self.values = self.locals.values
+ self.keys = self.locals.keys
+ self.items = self.locals.items
+
+ def add_module(self, node):
+ self.locals[node.name] = node
+ self.modules.append(node)
+
+ def get_module(self, name):
+ return self.locals[name]
+
+ def get_children(self):
+ return self.modules
+
+ def __repr__(self):
+ return f"<Project {self.name!r} at {id(self)} ({len(self.modules)} modules)>"
+
+
class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
"""Walk on the project tree and resolve relationships.
@@ -113,7 +142,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
# visited project
self.project = project
- def visit_project(self, node):
+ def visit_project(self, node: Project) -> None:
"""visit a pyreverse.utils.Project node
* optionally tag the node with a unique id
@@ -123,7 +152,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
for module in node.modules:
self.visit(module)
- def visit_module(self, node):
+ def visit_module(self, node: nodes.Module) -> None:
"""visit an astroid.Module node
* set the locals_type mapping
@@ -137,7 +166,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
if self.tag:
node.uid = self.generate_id()
- def visit_classdef(self, node):
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
"""visit an astroid.Class node
* set the locals_type and instance_attrs_type mappings
@@ -166,7 +195,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
except astroid.InferenceError:
node.implements = []
- def visit_functiondef(self, node):
+ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
"""visit an astroid.Function node
* set the locals_type mapping
@@ -183,7 +212,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
link_class = visit_classdef
link_function = visit_functiondef
- def visit_assignname(self, node):
+ def visit_assignname(self, node: nodes.AssignName) -> None:
"""visit an astroid.AssignName node
handle locals_type
@@ -224,7 +253,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
current | utils.infer_node(node)
)
- def visit_import(self, node):
+ def visit_import(self, node: nodes.Import) -> None:
"""visit an astroid.Import node
resolve module dependencies
@@ -234,7 +263,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
relative = astroid.modutils.is_relative(name[0], context_file)
self._imported_module(node, name[0], relative)
- def visit_importfrom(self, node):
+ def visit_importfrom(self, node: nodes.ImportFrom) -> None:
"""visit an astroid.ImportFrom node
resolve module dependencies
@@ -282,34 +311,6 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
mod_paths.append(mod_path)
-class Project:
- """a project handle a set of modules / packages"""
-
- def __init__(self, name=""):
- self.name = name
- self.path = None
- self.modules = []
- self.locals = {}
- self.__getitem__ = self.locals.__getitem__
- self.__iter__ = self.locals.__iter__
- self.values = self.locals.values
- self.keys = self.locals.keys
- self.items = self.locals.items
-
- def add_module(self, node):
- self.locals[node.name] = node
- self.modules.append(node)
-
- def get_module(self, name):
- return self.locals[name]
-
- def get_children(self):
- return self.modules
-
- def __repr__(self):
- return f"<Project {self.name!r} at {id(self)} ({len(self.modules)} modules)>"
-
-
def project_from_files(
files, func_wrapper=_astroid_wrapper, project_name="no name", black_list=("CVS",)
):
diff --git a/pylint/pyreverse/main.py b/pylint/pyreverse/main.py
index 601e67252..630146790 100644
--- a/pylint/pyreverse/main.py
+++ b/pylint/pyreverse/main.py
@@ -196,7 +196,7 @@ OPTIONS = (
class Run(ConfigurationMixIn):
"""base class providing common behaviour for pyreverse commands"""
- options = OPTIONS # type: ignore
+ options = OPTIONS
def __init__(self, args: Iterable[str]):
ConfigurationMixIn.__init__(self, usage=__doc__)
diff --git a/pylint/testutils/reporter_for_tests.py b/pylint/testutils/reporter_for_tests.py
index b1b7af7e4..b9e01b5a4 100644
--- a/pylint/testutils/reporter_for_tests.py
+++ b/pylint/testutils/reporter_for_tests.py
@@ -15,7 +15,9 @@ class GenericTestReporter(BaseReporter):
__implements__ = interfaces.IReporter
- def __init__(self): # pylint: disable=super-init-not-called
+ def __init__(
+ self,
+ ): # pylint: disable=super-init-not-called # See https://github.com/PyCQA/pylint/issues/4941
self.reset()
def reset(self):
diff --git a/setup.cfg b/setup.cfg
index c04b0a820..8d5ff9044 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -84,6 +84,7 @@ src_paths = pylint
[mypy]
scripts_are_modules = True
+warn_unused_ignores = True
[mypy-astroid.*]
ignore_missing_imports = True
diff --git a/tests/extensions/test_check_docs.py b/tests/extensions/test_check_docs.py
index aa8a700f0..f462ea3d1 100644
--- a/tests/extensions/test_check_docs.py
+++ b/tests/extensions/test_check_docs.py
@@ -341,7 +341,7 @@ class TestParamDocChecker(CheckerTestCase):
with self.assertNoMessages():
self.checker.visit_functiondef(node)
- def _visit_methods_of_class(self, node):
+ def _visit_methods_of_class(self, node: nodes.ClassDef) -> None:
"""Visit all methods of a class node
:param node: class node
diff --git a/tests/functional/g/generated_members.py b/tests/functional/g/generated_members.py
index b79c008dd..2b3a2b07d 100644
--- a/tests/functional/g/generated_members.py
+++ b/tests/functional/g/generated_members.py
@@ -1,7 +1,7 @@
"""Test the generated-members config option."""
# pylint: disable=pointless-statement, invalid-name, useless-object-inheritance
from __future__ import print_function
-from astroid import node_classes
+from astroid import nodes
from pylint import checkers
class Klass(object):
@@ -11,7 +11,7 @@ print(Klass().DoesNotExist)
print(Klass().aBC_set1)
print(Klass().ham.does.not_.exist)
print(Klass().spam.does.not_.exist) # [no-member]
-node_classes.Tuple.does.not_.exist
+nodes.Tuple.does.not_.exist
checkers.base.doesnotexist()
session = Klass()
diff --git a/tests/functional/g/generated_members.rc b/tests/functional/g/generated_members.rc
index 31b87ffd0..5f8f9cd0f 100644
--- a/tests/functional/g/generated_members.rc
+++ b/tests/functional/g/generated_members.rc
@@ -6,6 +6,6 @@ generated-members=
\Afunctional\.g\.generated_members\.Klass\.ham\Z,
DoesNotExist,
"[a-zA-Z]+_set{1,2}",
- node_classes.Tuple.*,
+ nodes.Tuple.*,
checkers.*?base,
(session|SESSION).rollback
diff --git a/tests/functional/u/unused/unused_variable.py b/tests/functional/u/unused/unused_variable.py
index 8e164acd1..84ca8c50f 100644
--- a/tests/functional/u/unused/unused_variable.py
+++ b/tests/functional/u/unused/unused_variable.py
@@ -79,8 +79,8 @@ def function(matches):
index += 1
print(match)
-
-def visit_if(self, node):
+from astroid import nodes
+def visit_if(self, node: nodes.If) -> None:
"""increments the branches counter"""
branches = 1
# don't double count If nodes coming from some 'elif'
diff --git a/tests/pyreverse/test_utils.py b/tests/pyreverse/test_utils.py
index e11002035..1d231eafa 100644
--- a/tests/pyreverse/test_utils.py
+++ b/tests/pyreverse/test_utils.py
@@ -80,7 +80,7 @@ def test_get_annotation_assignattr(init_method, label):
@patch("pylint.pyreverse.utils.get_annotation")
-@patch("astroid.node_classes.NodeNG.infer", side_effect=astroid.InferenceError)
+@patch("astroid.nodes.NodeNG.infer", side_effect=astroid.InferenceError)
def test_infer_node_1(mock_infer, mock_get_annotation):
"""Return set() when astroid.InferenceError is raised and an annotation has
not been returned
@@ -93,7 +93,7 @@ def test_infer_node_1(mock_infer, mock_get_annotation):
@patch("pylint.pyreverse.utils.get_annotation")
-@patch("astroid.node_classes.NodeNG.infer")
+@patch("astroid.nodes.NodeNG.infer")
def test_infer_node_2(mock_infer, mock_get_annotation):
"""Return set(node.infer()) when InferenceError is not raised and an
annotation has not been returned