Skip to content

Commit

Permalink
Support forward references for function-redefined check.
Browse files Browse the repository at this point in the history
Close #2540
  • Loading branch information
PCManticore committed Sep 15, 2019
1 parent ccea762 commit 2a5c1ab
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Expand Up @@ -7,6 +7,10 @@ What's New in Pylint 2.4.0?

Release date: TBA

* Support forward references for ``function-redefined`` check.

Close #2540

* Added a new check, ``consider-using-sys-exit``

This check is emitted when we detect that a quit() or exit() is invoked
Expand Down
19 changes: 14 additions & 5 deletions pylint/checkers/base.py
Expand Up @@ -171,6 +171,7 @@ def get_regex(cls, name_type):
COMPARISON_OPERATORS = frozenset(("==", "!=", "<", ">", "<=", ">="))
# List of methods which can be redefined
REDEFINABLE_METHODS = frozenset(("__module__",))
TYPING_FORWARD_REF_QNAME = "typing.ForwardRef"


def _redefines_import(node):
Expand Down Expand Up @@ -820,13 +821,11 @@ def _check_in_loop(self, node, node_name):
def _check_redefinition(self, redeftype, node):
"""check for redefinition of a function / method / class name"""
parent_frame = node.parent.frame()

# Ignore function stubs created for type information
redefinitions = parent_frame.locals[node.name]
defined_self = next(
(
local
for local in parent_frame.locals[node.name]
if not utils.is_overload_stub(local)
),
(local for local in redefinitions if not utils.is_overload_stub(local)),
node,
)
if defined_self is not node and not astroid.are_exclusive(node, defined_self):
Expand All @@ -842,6 +841,16 @@ def _check_redefinition(self, redeftype, node):
if utils.is_overload_stub(node):
return

# Check if we have forward references for this node.
for redefinition in redefinitions[: redefinitions.index(node)]:
inferred = utils.safe_infer(redefinition)
if (
inferred
and isinstance(inferred, astroid.Instance)
and inferred.qname() == TYPING_FORWARD_REF_QNAME
):
return

dummy_variables_rgx = lint_utils.get_global_option(
self, "dummy-variables-rgx", default=None
)
Expand Down
9 changes: 9 additions & 0 deletions tests/functional/f/function_redefined_2540.py
@@ -0,0 +1,9 @@
# pylint: disable=missing-module-docstring,missing-class-docstring,too-few-public-methods,invalid-name

from typing import ForwardRef

Cls = ForwardRef("Cls")


class Cls:
pass
2 changes: 2 additions & 0 deletions tests/functional/f/function_redefined_2540.rc
@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.7

0 comments on commit 2a5c1ab

Please sign in to comment.