summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--pylint/checkers/base.py19
-rw-r--r--tests/functional/f/function_redefined_2540.py9
-rw-r--r--tests/functional/f/function_redefined_2540.rc2
4 files changed, 29 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 432dd90be..0d4d4dc9b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py
index df564e0fc..2a1e90497 100644
--- a/pylint/checkers/base.py
+++ b/pylint/checkers/base.py
@@ -171,6 +171,7 @@ REVERSED_COMPS = {"<": ">", "<=": ">=", ">": "<", ">=": "<="}
COMPARISON_OPERATORS = frozenset(("==", "!=", "<", ">", "<=", ">="))
# List of methods which can be redefined
REDEFINABLE_METHODS = frozenset(("__module__",))
+TYPING_FORWARD_REF_QNAME = "typing.ForwardRef"
def _redefines_import(node):
@@ -820,13 +821,11 @@ class BasicErrorChecker(_BasicChecker):
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):
@@ -842,6 +841,16 @@ class BasicErrorChecker(_BasicChecker):
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
)
diff --git a/tests/functional/f/function_redefined_2540.py b/tests/functional/f/function_redefined_2540.py
new file mode 100644
index 000000000..25792295e
--- /dev/null
+++ b/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
diff --git a/tests/functional/f/function_redefined_2540.rc b/tests/functional/f/function_redefined_2540.rc
new file mode 100644
index 000000000..a17bb22da
--- /dev/null
+++ b/tests/functional/f/function_redefined_2540.rc
@@ -0,0 +1,2 @@
+[testoptions]
+min_pyver=3.7